现在的位置: 首页 > 综合 > 正文

C# Keywords Series 4 delegate&event

2013年03月19日 ⁄ 综合 ⁄ 共 4551字 ⁄ 字号 评论关闭

    本篇文章主要就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

     如果有错,欢迎纠正

   

   

   

   

   

抱歉!评论已关闭.