• 全面讲解:委托、事件


    每个编程者在项目中必定绕不开的话题:委托和事件。对于初学者来说,总会感觉有些难以理解,或者说无法自己随意运用。本文对委托、事件做一个详细的讲解,即是基础知识的自我温故,同时亦是记录。篇幅有些长,如果认真阅读,相信你会有所收获。

    《Introducing Visual C# 2010》(Adam Freeman著,Apress出版)一书的第10章中有这样的介绍:

    Delegates are special types thatencapsulate a method, similar to function pointers found in other programminglanguages. Delegates have a number of uses in C#, but you are most likely toencounter a special type of delegate—the event. Events make notifyinginterested parties simple and flexible, and I’ll explain the convention fortheir use later in the chapter.

    委托是封装方法的特殊类型,它类似于其它编程语言中的函数指针。委托在C#中有大量运用,但你最可能遇到的是一种特殊的委托类型— 事件。事件使得对相关部件的通知变得简单而灵活,本章后面将解释其使用约定。

    I’ll also explain the Func and Action typesthat let you use delegates in a more convenient form and that are usedextensively in some of the latest C# language features, such as parallelprogramming. We’ll finish up this chapter with a look at anonymous methods andlambda expressions, two C# features that let us implement delegates withouthaving to define methods in our classes.

    我也会解释Func和Action类型,它们让你以更方便的形式使用委托,而且在一些最新的C#特性中也有广泛使用,如并行编程。本章最后考察匿名方法和lambda表达式,这是让我们不必在类中定义方法就可以使用委托的两个C#特性。

    委托:

    委托定义:将函数作为另一个函数的参数进行调用。另外的解释:当一个类或者是进程需要调用另外一个方法时,需要借助另外的类或者是进程进行调用,这种机制称为委托。网上有大牛说:委托可以理解为函数指针,不同的是委托是面向对象、类型安全的。

    实现步骤:

    1、声明一个委托类型:

    public delegate int CalculateDelegate(int x, int y);

    2、定义一个委托对象:

    CalculateDelegate calculateDelegate = new CalculateDelegate(Add);

    其中Add是委托封装的方法;

    3、执行委托方法:

    calculateDelegate(2, 3);

    其中委托绑定的方法Add:

    public static int Add(int x, int y)
    { return x + y;}

    事件:

    事件是一种特殊类型的委托

    拿winform中button双击举例说明委托可能更加贴切:

    声明一个委托,并声明一个事件:

    public delegate void EventHandler(object sender, EventArgs e);
    public event EventHandler Click;

    绑定一个事件:

    this.button1.Click += new System.EventHandler(this.button1_Click);

    this.button1_Click是一个方法:

    private void button1_Click(object sender, EventArgs e){}

    拿一个实际项目举例说明:

    匿名方法:

    匿名方法(Anonymous methods) 提供了一种传递代码块作为委托参数的技术。匿名方法是没有名称只有主体的方法。在匿名方法中您不需要指定返回类型,它是从方法主体内的 return 语句推断的。

    在之前讲解委托时写到绑定方法:

    CalculateDelegate calculateDelegate = new CalculateDelegate(Add);
    public static int Add(int x, int y)
    {
    return x + y;
    }

    如果使用匿名方法重写上面的代码:

    CalculateDelegate calculateDelegate = delegate(int x, int y){return x + y;};

    可见:匿名方法绑定委托直接省去了编写一个单独的方法,使得代码更为简洁。

    项目中,使用委托时,很多时候编辑器会帮助我们把方法直接放入合适的委托对象中,但有时候编辑器帮助不了我们,比如:Control.Dispatcher.Invoke(delegate). 例如:

    this.btnExit .Dispatcher .Invoke (new Action(() => {}));

    Lambda表达式:

    Lambda 表达式是一种匿名函数,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字;

    C#的Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。语法如下:

    (object argOne, object argTwo) => {; /*Your statement goes here*/}

    用Lambda表达式重写上面使用匿名方法编写的委托实例,在匿名方法的基础上,编写如下:

    方式一:

    CalculateDelegate calculateDelegate = (int x, int y) => { return x + y; };

    方式二,更简单的表达:

    CalculateDelegate calculateDelegate = (x, y) => { return x + y; };

    方式三,再简单:

    CalculateDelegate calculateDelegate = (x, y) => x + y;

    从上面可以看出,Lambda仅仅是在匿名方法的基础上加上 => 符号,但是却让整个代码实现起来显得更为优雅。 

    泛型委托:

    在.net平台下有Microsoft自带的泛型委托,如:Action,Action<T>,Fun<T>等。实际使用中,如果需要用到泛型委托,系统内置的委托基本上就能满足需求了,下面一一介绍它们的原型及调用实例。

    Action

    系统封装的Action委托,没有参数没有返回值。调用实例为:

    public delegate void Action();
    static void Main(string[] args)       
    {
      Action action = new Action(Method);
      action();
    }
    private static void Method()
    {
      Console.WriteLine("i am is a action");
    }

    如果方法的表达很简单,可以使用Lambda表达式,代码如下: 

    Action action = () => { Console.WriteLine("i am is a action"); };

    Action<T>

    系统封装的Action<T>委托,有参数但是没有返回值。调用实例为:

    public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
    static void Main(string[] args)        
    {
      Action<int,int> action = new Action<int,int>(Method);
      action(2,3);
    }
    private static void Method(int x,int y)
    {
      Console.WriteLine("i am is a action");
    }

    使用Lambda表达式编写Action<T>代码如下:

    Action<int, int> action = (x, y) => { Console.WriteLine("i am is a action"); };

    Fun<T>

    系统封装的Fun<T>委托,有返回值。调用实例为:

    public delegate TResult Fun<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
    static void Main(string[] args) 
    {
      Fun<int, int, bool> fun = new Fun<int, int, bool>(Method);
      bool ret = fun(2,3);
    }
    private static bool Method(int x,int y)
    {

      if (x + y == 5) return true;
      else return false;
    }

    使用Lambda表达式编写Fun<T>,代码如下:

    Fun<int, int, bool> fun = (x, y) =>            
    {
      if (x + y == 5) return true;
      else return false;
    };

    Fun<T>没有参数有返回值的情况:

    Fun<bool> fun = () =>    
    {
      int x = 4;
      int y = 3;
      if (x + y == 5) return true;
      else return false;
    }; //也可以如此编写Fun<bool> fun = () => false;

      

    多播委托:

    最后说下多播委托,所谓多播委托,即 “多路广播委托”(MulticastDelegate)。从它的名字就可以看出,此种委托可以像广播一样将影响信息“传播”到四面八方。多播委托类拥有一个方法调用列表,调用委托时,它就会逐一调用该列表中的方法,从而实现多重影响。比较简单,暂不举例说明了。

    本文暂且告一段落,如果想查看更多文章,请关注“小项目笔记”公众号;

    如有疑问:可加入QQ群号:732982683

  • 相关阅读:
    20150316--TP-01
    20150314--TP-02
    20150314--TP-01
    20150313+微信-全
    表单/iframe与video标签
    图像/超链接标签
    HTML列表与表格
    JAVA新的一天
    MySQL常用函数
    php基础--来自网页转载
  • 原文地址:https://www.cnblogs.com/ysyn/p/12012517.html
Copyright © 2020-2023  润新知