zoukankan      html  css  js  c++  java
  • C#阶段提高之委托(delegate)

    委托是什么?

          委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。 您可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。您可以创建一个自定义方法,当发生特定事件时某个类(例如 Windows 控件)就可以调用您的方法。通俗地讲委托如其名字,就是我要办的事情交给一个方法来办理,这个方法可以作为参数传递其他方法。

         委托类型派生自 .NET Framework 中的 Delegate 类。 委托类型是 (sealed)密封的,不能从 Delegate 中派生委托类型,也不可能从中派生自定义类。 由于实例化委托是一个对象,所以可以将其作为参数进行传递,也可以将其赋值给属性。这样,方法便可以将一个委托作为参数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使用委托的代码无需了解有关所用方法的实现方面的任何信息。此功能类似于接口所提供的封装。

    以下是通过Reflector 7.0 反编译出来的微软.NET框架集中封装好的部分Delegate类的部分代码:

       1:  [Serializable, ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
       2:  public abstract class Delegate : ICloneable, ISerializable
       3:  {
       4:      // Fields
       5:      internal object _methodBase;
       6:      [ForceTokenStabilization]
       7:      internal IntPtr _methodPtr;
       8:      [ForceTokenStabilization]
       9:      internal IntPtr _methodPtrAux;
      10:      [ForceTokenStabilization]
      11:      internal object _target;
     

    反编译的代码仅供参考,不过大致可以看出这些定义的细节,获得delegate的设计里理念,明白为什么delegate是密封的,抽象的!

    使用委托:

       委托的定义与方法的定义相似,加上关键字delegate声明这是一个委托类型。同样可以存在自己的参数,形式如下:

       1:  public delegate void MyDelegates(string message);
     

         委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。 与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。上面的这个例子是封装一个字符串作为参数返回类型为空的委托。

         下面我通过一个排序的算法演示委托的使用方式,在这个演示的方法中我我提出进一步的请求完善这个排序。

         首先我的详细需求是,通过委托对一个数组进行排序,这个数组可以接受任何的对象(object),第一步先实现接受Int的排序,后续会实现string,以及类对象的排序等等,至于这个排序的方式完全有我们自己定义。

        先来声明一个委托,将来要接受一个方法作为参数,就是先来为我们自己设计的排序方式(方法)占个位置,后来我们自己的定义方法出来后有委托来实现。代码:

       1:  namespace SortDelegeter
       2:  {
       3:      public delegate int SortAnyDelegeter(object obj1,object obj2);
       4:  }

    下面继续通过一个类实现排序的基本思路功能:这个类文件名字叫做SortAnything.cs 核心代码:

       1:    public class SortAnything
       2:      {
       3:          //这里是对将要排序的对象的处理
       4:          public SortAnyDelegeter sortAnyDelegeter;
       5:          public void SortAny(object[] obj,SortAnyDelegeter sortDelegate)
       6:          {
       7:              for (int i = 0; i < obj.Length-1; i++)
       8:              {
       9:                  for (int j = 0; j < obj.Length - 1 - i; j++)
      10:                  {
      11:                      if (sortDelegate(obj[j + 1], obj[j]) < 0)
      12:                      {
      13:                          object temp = obj[j];
      14:                          obj[j]=obj[j+1];
      15:                          obj[j + 1] = temp;
      16:   //地方有限,节约缩进的距离  
      17:   }} }  }  }

    在这个类中我们首先将委托初始化,设置委托类型的变量sortAnyDelegeter,然后在排序方法中使用委托,这个排序方法传递两个参数一个是排序的对象,另一个是使用的委托对象。在11行的代码中我们开始使用委托,传入委托的两个参数。这里请注意委托的返回类型是Int,因此这里我们可以直接比较大于小于0.基本算法的内部还是基本的冒泡排序。

    我们的主方法的调用中可以实现这样的代码:

       1:   class Program
       2:      {
       3:          static void Main(string[] args)
       4:          {
       5:              //排序的算法使用委托完成(任意数据。字符的排序)
       6:              SortAnything sort = new SortAnything();
       7:              //int[] number = new int[] { 32, 2, 34, 2, 13, 32, 12 };
       8:              //这种定义方式有错误,
       9:              //因为int[]的数组不允许隐式转换为object[]数组
      10:              object[] number = { 32,2,34,2,13,32,12};
      11:              sort.SortAny(number, SortNumber);
      12:              //输出数组
      13:              for (int i = 0; i < number.Length; i++)
      14:              {
      15:                  Console.WriteLine(number[i].ToString());
      16:              }
      17:   
      18:          }
      19:   
      20:          //排序数字类型的委托,实现方法
      21:          public static int SortNumber( object a,object b)
      22:          {
      23:              return (int)a - (int)b;
      24:          }
      25:      }

           21-25行的代码具体定义比较的方法,这个方法既是当年我们处心积虑使用委托占用的位置。委托当年的占位就是为了这位同学啊!当地委托是怎么实现功能的呢?我们来看11行的代码,通过类对象加点来访问冒泡排序的方法,参数是两个即(排序对象,委托的服务对象,也就是那个被委托的方法),这既是委托,可以经现有的方法直接传给委托的实例,也就是说委托占的位置让这个方法(SortNumber)坐上了。在这里被委托的方法就是SortNumber(object a,object b)。这样就可以实现排序了。

          到此为止,已经使用了委托的方式。然而先来来了一个字符串数组也要排序,总不能也是用这个方法排序吧,要是这样,排序结果肯定使你头疼。我们可以重新写一个方法对这个字符串数字排序,只需定义排序规则而已。

       1:       public static int SortString(object a, object b)
       2:          {
       3:              //这里不写自己的方法了,借用预定义,从简!只为了说明委托
       4:              return String.Compare((string)a, (string)b);
       5:          }

    在使用的时间,顶替上面10,11行的代码改写为:

       1:      //object[] number = { 32,2,34,2,13,32,12};
       2:              object[] number = { "I ","Love","You","Do","You","Know" };
       3:              sort.SortAny(number, SortString);
       4:              //输出数组
       5:              for (int i = 0; i < number.Length; i++)
       6:              {
       7:                  Console.WriteLine(number[i].ToString());
       8:              }

    不仅仅如此,我们还可以无限扩展,当然这种扩展没有牵涉到设计模式,设计的有良性,只是为了演示简单的委托使用。

    什么时间使用委托:

         委托的基本性质就是这样的,那么什么时间使用委托呢?

    1. –多线程
    2. –自定义类(控件、通信类……(事件))
    3. –窗体之间回传值
    4. –正则表达式中替换Email掩码Replace()
    5. –…

    这些只是委托的部分知识,深入研究委托,事件,委托的多播等等只是会更好加深委托的使用。

  • 相关阅读:
    Python内置函数(14)——delattr
    Python内置函数(13)——complex
    Python内置函数(12)——compile
    Python内置函数(11)——classmethod
    Python内置函数(10)——chr
    Python内置函数(9)——callable
    Python内置函数(8)——bytes
    Python内置函数(7)——bytearray
    Python内置函数(6)——bool
    Python内置函数(4)——ascii
  • 原文地址:https://www.cnblogs.com/sunBolg/p/2496760.html
Copyright © 2011-2022 走看看