委托在c# 1 时代产生出来的。其对C#的发展产生了深远的影响。委托是将一个特定的方法绑定到一个特定的对象上。
委托类型直接派生雨System.MulticastDelgate类型。委托类型成员中最为重要的是Invoke方法,Invoke 方法决定了委托类型可以如何使用。同时绑定到委托的方法的签名都必须与Invoke的方法签名一致。
例如:delegate void Add(int a,int b) 类型的Invoke方法签名会类似 virturl void Invoke(int ,int);
委托对象维护两个字段:1.方法指针;2.目标对象的引用。委托执行会直接使用目标对象的引用地址JMP到方法的地址执行方法。
c#1 要创建委托实例。必须指定委托的类型和操作。
- 声明委托 public delegate bool CompareHandler(int x,int y);
- 操作方法:
public bool CompareData(int x,int y) { return x>y; }
- 绑定 CompareHandler handler = new CompareHandler(CompareData);
- 构建链式委托采用 Delegate.Combine(handler,...) , Delegate.Remove();
c# 2.0 时代加入了语法糖 += ,-=构建链式委托.同时支持委托的协变与逆变。
方法组转换:
方法组就是重载方法。方法组可以隐式转换为兼容的委托。
public delegate void EventHandler(object o,EventArgs e); public TestMethod(){} public TestMethod(object o,EventArgs e){} EventHandler h=TestMethod;
不过 方法组不能隐式的转换Delegate, 显示转换如下
Delegate d = (EventHandler)TestMethod
并且对于已经重载转换委托类型的方法,就不能把它作为方法参数使用,下面的 就会出现错 参数 1: 无法从“方法组”转换为“System.Delegate”
public delegate void EventHandler(object o, EventArgs e); public static void TestMehod(object o, EventArgs e) { } public static void TestMethodt(Delegate d) { } TestMethodt(TestMehod);
需要采用强制转型 TestMethodt((EventHandler)TestMehod);
委托匿名方法转换
匿名方法转换 在ECMA 344 13.5
1.无返回类型参数匹配
Action<int> s = delegate{ };
Action<int> a = delegate(int x) { };
2.匿名方法闭包:
闭包 抓取的是就是变量本身。如下的两种情况。对于counter来说List中抓的都是新的实例。对于i所有的list都是同一个变量
List<Action> lst = new List<Action>(); for (int i=0;i<3;++i) { int counter = i*10; lst.Add(delegate { Console.WriteLine("values is "+i); i++; }); } foreach (var t in lst) { t(); } lst[0](); lst[0](); lst[2](); lst[2]();
List<Action> lst = new List<Action>(); for (int i=0;i<3;++i) { int counter = i*10; lst.Add(delegate { Console.WriteLine("values is " + counter); counter++; });} foreach (var t in lst){ t(); } lst[0]();lst[0]();lst[2]();lst[2]();
匿名方法到lamda表达式:
public static void GetString() { ExtString(i => { i += "Hel World!"; Console.Write(i); }); } public static void ExtString(Action<string> i) { const string mol = "I Love "; i.Invoke(mol); }
lamda表达式本身就是匿名函数。匿名函数的要求也适用于它。捕获变量的生命周期也与匿名方法一样。