C# Keywords Series 4 delegate&event

来源:互联网 发布:淘宝差评报复 编辑:程序博客网 时间:2024/06/09 17:35
    本篇文章主要就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

     如果有错,欢迎纠正


   

   

   

   

   

原创粉丝点击