C#的委托类型可以定义一个委托变量,其值是一个类的方法,相当于类型安全的函数指针。它有两个重要概念:协变和逆变。
协变允许委托方法返回值的类型是定义委托方法返回值的类型的派生类(子类),例如:(来自vs2010 help library)
class Mammals{}
class Dogs : Mammals{}
class Program
{
// Define the delegate.
public delegate Mammals HandlerMethod();
public static Mammals MammalsHandler()
{
return null;
}
public static Dogs DogsHandler()
{
return null;
}
static void Test()
{
HandlerMethod handlerMammals = MammalsHandler;
// Covariance enables this assignment.
HandlerMethod handlerDogs = DogsHandler;
}
}
逆变允许委托方法的参数是原定义的委托方法的基类(父类)
private void MultiHandler(object sender, System.EventArgs e)
{
label1.Text = System.DateTime.Now.ToString();
}
public Form1()
{
InitializeComponent();
this.button1.KeyDown += this.MultiHandler;
this.button1.MouseClick += this.MultiHandler;
//EventArgs 是KeyDown 和 MouseClick 相对应参数 的基类
}
从上面例子来看委托可以进行加减运算,加运算相当于将同样类型的委托实例组合到一个委托实例中去,那个拥有其他委托实例的委托实例就像一个集合容器一样。一但执行委托实例映射的方法,这个委托实例内容纳所有的委托实例都会执行其映射的方法。看例子:
delegate void Del(string s);
class TestClass
{
static void Hello(string s)
{
System.Console.WriteLine(" Hello, {0}!", s);
}
static void Goodbye(string s)
{
System.Console.WriteLine(" Goodbye, {0}!", s);
}
static void Main()
{
Del a, b, c, d;
a = Hello;
b = Goodbye;
c = a + b;
d = c - a;
System.Console.WriteLine("Invoking delegate a:");
a("A");
System.Console.WriteLine("Invoking delegate b:");
b("B");
System.Console.WriteLine("Invoking delegate c:");
c("C");
System.Console.WriteLine("Invoking delegate d:");
d("D");
}
}
从上面例子(来自vs2010 help library)可以知道,- 运算符可用来从组合的委托移除组件委托。好了,这就是C#的合并委托,或多路广播.
官方定义:
委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。
委托对象的一个用途在于,可以使用 + 运算符将它们分配给一个要成为多路广播委托的委托实例。
当向委托分配一个方法时,协变和逆变会提供用于使委托类型与方法签名匹配的灵活性。
协变允许方法具有的派生返回类型比委托中定义的更多(派生类)。