委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。
对函数特征的匹配要求并不是完全严格的:方法不必与委托类型完全匹配。
感觉像函数指针?官方文档:委托类似于 C++ 函数指针,但委托完全面向对象,不像 C++ 指针会记住函数,委托会同时封装对象实例和方法。
函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。
可以用来实现多态,想想和C++虚函数有什么关系吗
对比事件
delegate <return type> <delegate-name> <parameter list>; public delegate void printString(string s); // 声明委托,表明了能绑定的函数的特征,包括返回值 // 看起来像是函数声明,但应该是声明了一个“类型”,这个类型描述了和其匹配的函数的要求 // printString变成了一个像类型名一样的东西
<delegate-name> <instance-name> = new <delegate-name>(<function-name>); printString ps1 = new printString(WriteToScreen); printString ps2 = new printString(WriteToFile); // 就好像一个变量绑定了一个函数
ps1("Hi"); // 把变量像函数一样使用 printString ps3 = ps1; // 变量还方便传递 // 委托也可以使用Invoke进行触发
NumberChanger nc; NumberChanger nc1 = new NumberChanger(AddNum); NumberChanger nc2 = new NumberChanger(MultNum); nc = nc1; nc += nc2; // 将两个委托合并起来 nc(5); // 调用多播
namespace Zhonghui { class MainApp { private string m_kName; public MainApp(string Name) { m_kName = Name; } // 非静态函数,可以访问this private void ASay(string Text) { Console.WriteLine(this.m_kName + "'s A:" + Text); } private void BSay(string Text) { Console.WriteLine(this.m_kName + "'s B:" + Text); } // 静态函数 public static void StaticSay(string Text) { Console.WriteLine("Static Say:" + Text); } public delegate void Say(string Text); static void Main() { var MainA = new MainApp(new string("Apple")); var MainB = new MainApp(new string("Banana")); // 绑定非静态函数:Object.Function // 委托是和这个具体对象关联的 var A = new Say(MainA.ASay); // Apple的A函数 var B = new Say(MainB.BSay); // Banana的B函数 // 绑定静态函数:Class.Function var AB = A + B + new Say(MainApp.StaticSay); // 同时调用3个函数 A("I am A"); B("I am B"); AB("We are A & B"); } } }
首先:“通用委托”是我自己起的名字,指的是Action,Func和Predicate
这些东西是为了干啥呢?首先,声明委托像是声明一个类型,委托不同也就是其匹配的参数列表和返回值不同,所以,其实不用为了使用一次委托而单独声明一种类型,使用通用的就可以了
演示一下:
namespace Zhonghui { class MainApp { static void Main() { // Action匹配类型:可以有参数(也可以没有),不能有返回值 var P = new Action<string>(Print); // Func匹配类型:可以有参数(也可以没有),必须有返回值 // <>里面最后一个是返回值类型,前面写参数类型列表 var A = new Func<float, float, int>(Add); // Predicate匹配类型:有且只有一个参数,返回值必须为bool var I = new Predicate<int>(IsZero); // 调用都是和普通委托一样 P("Action"); Console.WriteLine(A(1, 2)); Console.WriteLine(I(0)); } // 有参数,没有返回值 static void Print(string Text) { Console.WriteLine(Text); } // 有参数,也有返回值 static int Add(float x,float y) { return (int)(x + y); } // 只有一个参数,返回值是bool static bool IsZero(int x) { return (x == 0); } } }