一:什么是委托
委托是一种定义方法签名的类型class="sentence" data-guid="07f47fe690b1cb6829dea61376019fcb" data-source="When you instantiate a delegate, you can associate its instance with any method with a compatible signature.">当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。委托是一个引用类型,所以它具有引用类型所具有的通性。它保存的不是实际值,而是保存对存储在托管堆(managed heap)中的对象的引用。 委托可以引用静态方法和非静态方法。
通俗的理解是,委托其实可以是一种简单的约束,好比在工作上我声明了一个委托人A, A同时可以接受(人力资源,后勤公务)两个参数,那么只要是有人想处理(人力资源,后勤)方面的事情,都可以去注册到委托人A上,A有能力接受这些方法,然后去处理。
二:委托的声明
声明委托可以通过delegate来声明,委托可以依赖于一个类,也可以依赖于一个namespace间。即 在类里面声明和在类外面声明。其中delegate可以有返回类型和非返回类型,其中delegate也支持泛型。
public delegate double AddNum(double num1,double num2); public delegate void ShowMsg(string str);
三: 委托的使用
1. 基本使用:下面是一个计算方法,声明了一个委托CalculatorDelegate,然后在Main方法里面先后注册了AddNum,和SumNum方法,注册的方法必须与委托的参数以及返回类型相符合,否者将会提示【委托与注册方法不匹配的提示】对于这块是直接编译无法通过的。委托如果被注册了多个方法,称为多播。对于多播,调用委托后,按照注册顺序执行。不过对于有返回值的方法,将返回最后注册的方法执行后的返回值。
Notes:第一次注册方法的时候可以使用【=注册】或者【new CalculatorDelegate(方法名) 】,后面添加方法用【+】,取消注册方法用【-】
运行代码和运行结果如下图:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SpongeBobCoder.Delegate { public delegate double CalculatorDelegate(double num1, double num2); // 委托,声明在类之外 public class Program { public static double AddNum(double num1, double num2) { Console.WriteLine("Sum={0}", num1 + num2); return num1 + num2; } public static double SubNum(double num1, double num2) { Console.WriteLine("Sub={0}", num1 - num2); return num1 - num2; } public static void Main(string[] args) { CalculatorDelegate calculatorDel = AddNum; // 目前为单播 Console.WriteLine("委托一个方法的结果为:{0}", calculatorDel(1, 2)); calculatorDel += SubNum; // 目前是多播 Console.WriteLine("委托两个方法的结果为:{0}", calculatorDel(1, 2)); Console.ReadKey(); } } }
2. 委托注册方法的几种形式:除了上面的方式,其实委托的注册方法还支持Linq方法,匿名方法。其实在Linq中也大量的委托,比如在使用List<T>.where(),List<T>.sort()这些方法的时候其实里面就运用的大量的委托。其实可以理解为就是委托的缩影。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SpongeBobCoder.Delegate { public delegate double CalculatorDelegate(double num1, double num2); // 委托 public class Program { public static void Main(string[] args) { CalculatorDelegate calculatorDel = delegate(double x, double y) //等效于AddNum方法 { return x + y; }; Console.WriteLine("委托一个方法的结果为:{0}", calculatorDel(1, 2)); calculatorDel += (x, y) => // 等效于SumNum方法 { return x - y; }; Console.WriteLine("委托两个方法的结果为:{0}", calculatorDel(1, 2)); Console.ReadKey(); } } }
3. 小添加: 其实在.net框架提供了自带的委托. Action<T>,Func<T,out Result>。Action是无返回值泛型委托,Func是有返回值的泛型委托【out Result就是返回值,不过使用的时候不是要传入一个out参数,对于Action<T,T,out Result>,其实就是传入2个参数。】代码如下:
Notes:注意Func<>三个参数,可是AddNum只有两个,其实第三个就是对应的返回值,这里有别于我们前面说的委托,希望大家注意.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SpongeBobCoder.Delegate { public class Program { private static void ShowMsg(string str) { Console.WriteLine(str); } private static double AddNum(double num1, double num2) { return num1 + num2; } public static void Main(string[] args) { Action<string> action = ShowMsg; action("Action委托好用!"); Func<double, double, double> func = AddNum; // Notes Console.WriteLine("Func委托真好用,两数之和为:{0}", func(1, 2)); Console.ReadKey(); } } }
四:总结
因为最近在接触Silverlight,事件委托以后会不断接触。所以这两天看了一下事件委托的知识,并写博客记录一下。有什么理解不对,描述不对的还请各位博友指点指点。下篇会更新事件的使用。