將方法簽名與代理類型匹配時,協變和逆變為您提供了一定程度的靈活性。協變允許方法具有的派生返回類型比委托中定義的更多。逆變允許方法具有的派生參數類型比委托類型中的更少。
一、逆變
對於下面的三個代理類型:
[csharp]
delegate void EventHandler (object sender, EventArgs e)
delegate void KeyPressEventHandler (object sender, KeyPressEventArgs e)
delegate void MouseEventHandler (object sender, MouseEventArgs e)
由於KeyPressEventArgs和MouseEventArgs都繼承自EventArgs,因此,如果你有一個EventArgs參數的方法,你總能用一個KeyPressEventArgs類型的參數去掉用,因此用類似EventHandler簽名的方法去創建KeyPressEventHandler類型的代理對象就顯得有意義了。這正是C#2所支持的特性。
[csharp]
System.DateTime lastActivity;
public Form1()
{
InitializeComponent();
lastActivity = new System.DateTime();
this.textBox1.KeyDown += this.MultiHandler; //works with KeyEventArgs
this.button1.MouseClick += this.MultiHandler; //works with MouseEventArgs
}
// Event hander for any event with an EventArgs or
// derived class in the second parameter
private void MultiHandler(object sender, System.EventArgs e)
{
lastActivity = System.DateTime.Now;
}
二、協變
協變是針對返回值類型具有可轉換類型的情況,下面是協變的例子:
[csharp]
class Mammals
{
}
class Dogs : Mammals
{
}
class Program
{
// Define the delegate.
public delegate Mammals HandlerMethod();
public static Mammals FirstHandler()
{
return null;
}
public static Dogs SecondHandler()
{
return null;
}
static void Main()
{
HandlerMethod handler1 = FirstHandler;
// Covariance allows this delegate.
HandlerMethod handler2 = SecondHandler;
}
}