本篇文章主要就delegate和event的用法展开论述,对于委托和事件,原来确实不熟悉,所以希望能通过写这篇博客,加深了解。
delegate
delegate委托,简而言之就是方法签名(类似于c++中的函数指针,相对封装性好),是引用类型。下面是委托的声明:
public delegate void TestDelegate(string message); public delegate int TestDelegate(MyType m, long num);
可以看到类似方法的定义,但是没有方法体,定义前加上delegate关键字,可以认为是定义一个新类,所以在类的外部或者内部都行。在这里,还要介绍下Action<T>和Func<T>两种泛型委托。Action<in T1, in T2>表示一个调用两个参数(T1,T2)的无返回类型的委托。Func<in T, out TResult>表示一个带返回类型的含一个参数的委托,通常最后一个是返回类型。
Action<double> testDelegate1;//等同于delegate void testDelegate1(double param);
Func<double,double>testDelegate2;//等同于delegate double testDelegate2(double param);
下面我们来看看如何使用委托,上代码:
private delegate string GetAString(); static void Main(string[] args) { int x = 40; GetAString gs = new GetAString(x.ToString); Console.WriteLine("string is {0} ", gs()); } //output: //string is 40
委托还有两种使用方式,匿名方法和Lambda表达式(其实就是匿名方法,C#3.0以后用Lambda代替匿名方法),上述代码也可以改成如下代码:
GetAString gs2= delegate() { return x.ToString(); };//匿名方法实例化委托 GetAString gs3 = () => x.ToString();//Lambda表示是实例化委托
这样的效果都是一样的,这里说明下Lambda表达式的用法:(参数类型1 参数名1,参数类型2 参数2 ...)=> 单条语句 或者 {方法体花括号适用于多条语句 };
上面的截图转载的,很好的说明了Lambda表达式的进化。看来看去,会不会觉得委托的作用不是很大,是可以替代的,在下面的这个例子你会看到它的大用处。我们以前(学生时代)写的冒泡排序只针对基本类型的排序,对于对象的排序似乎捉襟见肘,不能直接用比较符号〈,假如我们将比较方法当作参数传入冒泡排序,不就可以了吗?这会体现了委托在泛型编程当中的作用,看代码:
namespace ConsoleApplication { class Program { static void Main(string[] args) { Employee[] ems ={ new Employee("Issac",2200), new Employee("TrisD",2000), new Employee("Wz",10000), new Employee("Abc",4000) }; BubbleSorter.Sort(ems, Employee.CompareSalary); foreach (var item in ems) { Console.WriteLine(item); } Console.ReadKey(); } } class Employee { public string Name { get; private set; } public decimal Salary { get; private set; } public Employee(string name,decimal salary) { this.Name=name; this.Salary=salary; } public override string ToString() { return string.Format("{0},{1:C}",Name,Salary); } public static bool CompareSalary(Employee e1, Employee e2) { return e1.Salary < e2.Salary; } } class BubbleSorter { static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison) { bool swapped = true; do { swapped = false; for (int i = 0; i < sortArray.Count-1; i++) { if (comparison(sortArray[i+1] , sortArray[i])) { T temp = sortArray[i]; sortArray[i] = sortArray[i + 1]; sortArray[i + 1] = temp; swapped = true; } } } while (swapped); } } } // output: //TrisD,$2,000.00 //Issac,$2,200.00 //Abc,$4,000.00 //Wz,$10,000.00
这样就实现了,传递方法泛型编程的效果。这只是简单的介绍,还有多播委托,事件就是一种特殊型的多播委托,支持 + - = 之类的运算,那就不多说了。
event
event 基于delegate,提供一种发布订阅机制, 声明方式如下:
public delegate void SampleEventHandler(object sender, EventArgs e);
public event SampleEventHandler SampleEvent;
可以通过Ispy查看EventHandler代码,实际上就是一个委托声明:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs : EventArgs;
目前我在学习SharePoint 2013 和 2010 的区别,下面我们通过SharePoint 2013 升级到2010 的事件学习事件的使用:
static class Program { static void Main(string[] args) { var sharePoint2010 = new SharePoint2010(); var sharePoint2013 = new SharePoint2013(); //订阅事件 sharePoint2013.beforeUpgradeEvent += sharePoint2013_beforeUpgradeEvent; sharePoint2013.afterUpgradeEvent += sharePoint2013_afterUpgradeEvent; sharePoint2013.Upgrade(sharePoint2010); } static void sharePoint2013_afterUpgradeEvent(object sender, AfterUpgradeEventArgs e) { Console.WriteLine("The upgrade process is {0}", e.IsSuccessful == true ? "successful" : "failed"); } static void sharePoint2013_beforeUpgradeEvent(object sender, BeforeUpgradeEventArgs e) { Console.WriteLine("Before upgrade..."); } } //声明委托 public delegate void BeforeUpgrade(object sender, BeforeUpgradeEventArgs e); public delegate void AfterUpgrade(object sender, AfterUpgradeEventArgs e); public class SharePoint2010 { } public class SharePoint2013 { public void Upgrade(SharePoint2010 sharePoint2010) { //更新过程 var beforeUpgrade = new BeforeUpgradeEventArgs(); Upgrading(beforeUpgrade); Console.WriteLine("During upgrade..."); var afterUpgrade = new AfterUpgradeEventArgs(true); Upgraded(afterUpgrade); } //声明事件 public event BeforeUpgrade beforeUpgradeEvent; public event AfterUpgrade afterUpgradeEvent; //触发事件 protected virtual void Upgrading(BeforeUpgradeEventArgs e) { //触发事件判断是否存在 if (beforeUpgradeEvent != null) { beforeUpgradeEvent(this, e); } } protected virtual void Upgraded(AfterUpgradeEventArgs e) { if (afterUpgradeEvent != null) { afterUpgradeEvent(this, e); } } } //升级前事件的发布 public class BeforeUpgradeEventArgs : EventArgs { public bool IsContinue { get; set; } public BeforeUpgradeEventArgs() { IsContinue = true; } } //升级后事件的发布 public class AfterUpgradeEventArgs : EventArgs { public bool IsSuccessful { get; private set; } public AfterUpgradeEventArgs(bool isSuccessful) { IsSuccessful = isSuccessful; } } //Before upgrade... //During upgrade... //The upgrade process is successful
通过这样一个例子,我想对于事件的了解更深刻了。另外说明下,如果是静态事件的话,触发事件的this参数还是要填上null的。
关于delegate和event的研究就这些,这里有更深入的讲解,是大牛的博客,贴一个:http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html
如果有错,欢迎纠正