委托参数的逆变性

读了深入理解C#书中的 5.3.1 委托参数的逆变性,记录一下。

先看一段代码:

public Form1()
{
    InitializeComponent();
    Button button1 = new Button {Text = "Click me 1", Location = new Point(22, 49)};
    Button button2 = new Button {Text = "Click me 2", Location = new Point(102, 49)};

    //  代码1
    button1.Click += LogPlainEvent;
    button1.KeyPress += LogKeyEvent;
    button1.MouseClick += LogMouseEvent;

    //  代码2
    button2.Click += LogEvent;
    button2.KeyPress += LogEvent;//使用了转换和逆变性
    button2.MouseClick += LogEvent;//使用了转换和逆变性

    this.Controls.Add(button1);
    this.Controls.Add(button2);
}

static void LogPlainEvent(object sender, EventArgs e)
{
    MessageBox.Show("LogPlain");
}
static void LogKeyEvent(object sender, KeyPressEventArgs e)
{
    MessageBox.Show("LogKey");
}
static void LogMouseEvent(object sender, MouseEventArgs e)
{
    MessageBox.Show("LogMouse");
}

static void LogEvent(object sender, EventArgs e)
{
    MessageBox.Show("An event occurred");
}

上面代码button涉及到的三个委托类型的签名如下:
public delegate void EventHandler(object sender, EventArgs e);
public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e);
public delegate void MouseEventHandler(object sender, MouseEventArgs e);
注意KeyPressEventArgs和MouseEventArgs都从EventArgs派生,所以,如果有一个方法要获取一个EventArgs参数,那么始终都可以在调用它时改为传递一个KeyPressEventArgs实参。
所以,用签名与EventHandler相同的一个方法来创建KeyPressEventHandler的一个实例是完全合乎情理的。

代码1地方使用了正常的方法组转换,代码2地方使用了转换和逆变性。

委托参数的逆变性

时间: 2024-10-13 15:05:56

委托参数的逆变性的相关文章

C#委托的协变性和逆变性

逆变性 只要函数参数与委托兼容,就能创建委托实例. 1 Button button = new Button(); 2 //public delegate void EventHandler(object sender, EventArgs e); 3 button.Click += LogPlainEvent; 4 //public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e); 5 button.

协变性和逆变性

1.协变性是指方法能返回从委托的返回类型派生的一个类型. 2.逆变性是指方法获取的参数可以是委托的参数类型的基类. =================================分割线================================= delegate Object MyCallback(FileStream s); string SomeMethod(Stream s); 如上面的例子,SomeMethod 的返回类型(string)派生自委托的返回类型(Object):这

Java 协变性、逆变性 [转]

n  协变性.逆变性和无关性 在面向对象的计算机程序语言中,经常涉及到类型之间的转换,例如从具体类小猫到动物之间的类型转换(上行转换),或者从形状向三角形之间的转换(下行转换). 协变性(covariance).逆变性(contravariance)和无关性(invariant).他们都是用来描述类型转换的性质的术语,形式化的描述如下: 如果A和B是类型,f表示类型转换,≤表示子类型关系,(例如A≤B,表示A是B的子类)那么: 如果A≤B 则f(A) ≤ f(B) 那么f是协变的 如果A≤B 则

使用委托参数的实例

using System; using System.Collections.Generic; using System.Linq; using System.Text; /*使用委托参数的实例 * 1.Func是Linq的预定义的委托类型 * 2.public delegate TR Func<TR>();//TR 为返回类型 * 3.public delegate TR Func<T1,TR>(T1 a1);//TR 为返回类型,<T1,TR>是类型参数,(T1 a

返回类型协变和参数类型逆变

class Animal { } class Dog : Animal { } class Program { static void Main(string[] args) { //返回类型协变 Func<Animal, Animal> s = doThing; //参数类型逆变 Action<Dog> s2 = doThing2; } static Dog doThing(Animal x) { return null; } static void doThing2(Anima

c#中关于协变性和逆变性(又叫抗变)详解

今天回忆了之前看的<深入理解C#>这本书中的泛型章节,其中对泛型的可变性的理解.泛型可变性分两种:协变和逆变.逆变也又称为抗变. 怎么理解这两个名词的意思: ①:协变即为在泛型接口类型中使用out标识的类型参数.协变的字面意思是"与变化的方向相同"②逆变那就是用in来标识的泛型接口类型的类型参数.逆变的字面意思是"与变化的方向相反" 需要注意的是无论是协变还是逆变也只能在泛型接口中来使用. 先来举个基本的例子,来加强你对可变性的理解.在C#中有隐式类型转

进入快速委托通道

笨拙的委托语法 C#1中,先写好一连串事件处理程序,然后写new EventHandler. #region 5-1 Button button = new Button(); button.Text = "Click me"; button.Click += new EventHandler(LogPlainEvent);//点击触发 button.KeyPress += new KeyPressEventHandler(LogKeyEvent); button.KeyPress +

匹夫细说C#:庖丁解牛聊委托,那些编译器藏的和U3D给的

0x00 前言 由于工作繁忙所以距离上一篇博客已经过去一个多月的时间了,因此决心这个周末无论如何也得写点东西出来,既是总结也是分享.那么本文主要的内容集中在了委托的使用以及内部结构(当然还有事件了,但是受制于篇幅故分为两篇文章)以及结合一部分Unity3D的设计思考.当然由于时间仓促,文中难免有一些疏漏和不准确,也欢迎各位指出,共同进步. 0x01 从观察者模式说起 在设计模式中,有一种我们常常会用到的设计模式——观察者模式.那么这种设计模式和我们的主题“如何在Unity3D中使用委托”有什么关

UNITY_委托和事件

UNITY_委托和事件 参考资料: Unity3D脚本编程-使用C#语言开发跨平台游戏-陈嘉栋 观察者模式 主题(Subject)管理某些数据,当主题的数据发生改变时,会通知已经注册(Register)的观察者(Observer),而这些已经注册的观察者会受到数据改变的通知并作出相应反应. 观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新. Unity提供的机制:SendMessage()和BroadcastMessage() 缺点: 过于依赖反射