代码改变世界

委托参数的逆变性

2014-08-13 16:16  张小驴同学  阅读(417)  评论(0编辑  收藏  举报

读了深入理解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地方使用了转换和逆变性。