星空网 > 软件开发 > ASP.net

[C#] C# 知识回顾

C# 知识回顾 - 委托 delegate

【博主】反骨仔    【原文】http://www.cnblogs.com/liqingwen/p/6031892.html

目录

  • What's 委托
  • 委托概述
  • Use 委托

 

What's 委托

  delegate 是表示对具有特定参数列表和返回类型的方法的引用的类型。在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。你可以通过委托实例调用方法。委托用于将方法作为参数传递给其他方法。 事件处理程序就是通过委托调用的方法。 你可以创建一个自定义方法,当发生特定事件时,某个类(如 Windows 控件)就可以调用你的方法。下面的示例演示了一个委托声明:

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





  可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。 该方法可以是静态方法,也可以是实例方法。 这样便能通过编程方式来更改方法调用,还可以向现有类中插入新代码。

  【备注】在方法重载的上下文中,方法的签名不包括返回值。 但在委托的上下文中,签名包括返回值。 换句话说,方法和委托必须具有相同的返回类型。

将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。 例如,对比较两个对象的方法的引用可以作为参数传递到排序算法中。由于比较代码在一个单独的过程中,因此可通过更常见的方式编写排序算法。

 


委托的属性概述

  • 委托类似于 C++ 函数指针,但它们是类型安全的。

  • 委托允许将方法作为参数进行传递。

  • 委托可用于定义回调方法。

  • 委托可以链接在一起;例如,可以对一个事件调用多个方法。

  • 方法不必与委托类型完全匹配。

  • C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递来代替单独定义的方法。 C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能现在统称为匿名函数。

 

Use 委托

  委托是安全封装方法的类型,类似于 C 和 C++ 中的函数指针。与 C 函数指针不同的是,委托是面向对象的、类型安全的和可靠的。委托的类型由委托的名称确定。

  //该委托可以封装 “名 MyDel,参数类型 string,返回类型 void” 的方法   public delegate void MyDel(string message);

 

  委托对象通常通过提供委托将封装的方法的名称或使用匿名方法构造。对委托进行实例化后,委托会将对其进行的方法调用传递到该方法。调用方传递到委托的参数将传递到该方法,并且委托会将方法的返回值(如果有)返回到调用方。这被称为调用委托。实例化的委托可以按封装的方法本身进行调用。  例如:

 1   //该委托可以封装 “名 MyDel,参数类型 string,返回值类型 void” 的方法  2   public delegate void MyDel(string message); 3  4   class Program 5   { 6     static void Main(string[] args) 7     { 8       //实例化委托 9       MyDel del = Print;10       //调用委托11       del("Hi");12 13       Console.Read();14     }15 16     /// <summary>17     /// 打印文本18     /// </summary>19     /// <remarks>这是一个可用于 MyDel 委托的方法</remarks>20     /// <param name="message"></param>21     private static void Print(string message)22     {23       Console.WriteLine(message);24     }25   }

[C#] C# 知识回顾

 

  委托类型派生自 .NET Framework 中的 Delegate 类。委托类型是封装的,它们不能派生出其他类,也不能从 Delegate 派生出自定义类。由于实例化的委托是一个对象,因此可以作为参数传递或分配给一个属性。这允许方法作为参数接受委托并在稍后调用委托。这被称为异步回调,是在长进程完成时通知调用方的常用方法。当以这种方式使用委托时,使用委托的代码不需要知道要使用的实现方法。功能类似于封装接口提供的功能。  
 
  回调的另一个常见用途是定义自定义比较方法并将该委托传递到短方法。  它允许调用方的代码成为排序算法的一部分。  以下示例方法使用 Del 类型作为参数:  
 1   class Program 2   { 3     static void Main(string[] args) 4     { 5       MyDel del = Print; 6       CallbackMethod(100, 150, del); //将委托传递到 CallbackMethod 方法 7  8       Console.Read(); 9     }10 11     /// <summary>12     /// 回调方法13     /// </summary>14     /// <param name="m"></param>15     /// <param name="n"></param>16     /// <param name="del"></param>17     private static void CallbackMethod(int m, int n, MyDel del)18     {19       del((m + n).ToString());20     }21 22     private static void Print(string message)23     {24       Console.WriteLine(message);25     }26   }

[C#] C# 知识回顾

 


  CallbackMethod 的作用是将字符串传递到其他方法。由于该方法可以使用任意数量的参数,此功能特别强大。 

 

  当委托构造为封装实例方法时,委托将同时引用实例和方法。  委托不知道除其所封装方法以外的实例类型,因此委托可以引用任何类型的对象,只要该对象上有与委托签名匹配的方法。  当委托构造为封装静态方法时,委托仅引用方法。  请考虑以下声明:  

 1   //该委托可以封装 “名 MyDel,参数类型 string,返回值类型 void” 的方法  2   public delegate void MyDel(string message); 3  4   class MyClass 5   { 6     public void Print1(string message) 7     { 8       Console.WriteLine($"{message} - {nameof(Print1)}"); 9     }10 11     public void Print2(string message)12     {13       Console.WriteLine($"{message} - {nameof(Print2)}");14     }15   }16 17   class Program18   {19     static void Main(string[] args)20     {21       var myClass = new MyClass();22       MyDel del1 = myClass.Print1;23       MyDel del2 = myClass.Print2;24       MyDel del3 = Print;25 26       var del = del1 + del2;27       del += del3;  //这里使用 +=28       del("Hi!");29 30       Console.Read();31     }32 33     private static void Print(string message)34     {35       Console.WriteLine($"{message} - {nameof(Print)}");36     }37   }

[C#] C# 知识回顾

 

  调用时,委托可以调用多个方法。  这被称为多播。  若要向委托的方法列表(调用列表)添加其他方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。

  此时,allMethodsDelegate 的调用列表中包含三个方法,分别为 Print1、Print2 和 Print。原有的三个委托(d1、d2 和 d3)保持不变。调用 allMethodsDelegate 时,将按顺序调用所有三个方法。  如果委托使用引用参数,引用将按相反的顺序传递到所有这三个方法,并且一种方法进行的任何更改都将在另一种方法上见到。  当方法引发未在方法内捕获到的异常时,该异常将传递到委托的调用方,并且不会调用调用列表中的后续方法。  如果委托具有返回值和/或输出参数,它将返回上次调用方法的返回值和参数。  若要删除调用列表中的方法,请使用减法运算符或减法赋值运算符(“+”或“-=”)。  例如:  

 1     static void Main(string[] args) 2     { 3       var myClass = new MyClass(); 4       MyDel del1 = myClass.Print1; 5       MyDel del2 = myClass.Print2; 6       MyDel del3 = Print; 7  8       var del = del1 + del2; 9       del += del3;  //使用 +=10       del("Hi!");11 12       Console.WriteLine("======分割线======");13 14       del -= del2;  //使用 -=15       del("Hi!");16 17       Console.Read();18     }

[C#] C# 知识回顾

 

  由于委托类型派生自 System.Delegate,因此可以在委托上调用该类定义的方法和属性。例如,若要查询委托调用列表中方法的数量,你可以编写:

 1     static void Main(string[] args) 2     { 3       var myClass = new MyClass(); 4       MyDel del1 = myClass.Print1; 5       MyDel del2 = myClass.Print2; 6       MyDel del3 = Print; 7  8       var del = del1 + del2; 9       del += del3;  //使用 +=10       //del("Hi!");11 12       var count = del.GetInvocationList().Length; //获取委托调用列表中方法的数量13       Console.WriteLine(count);14 15       Console.WriteLine("======分割线======");16 17       del -= del2;  //使用 -=18       //del("Hi!");19 20       count = del.GetInvocationList().Length; //获取委托调用列表中方法的数量21       Console.WriteLine(count);22 23       Console.Read();24     }

[C#] C# 知识回顾

 

  调用列表中具有多个方法的委托派生自 MulticastDelegate,该类属于 System.Delegate 的子类。  由于这两个类都支持 GetInvocationList,因此在其他情况下,上述代码也将产生作用。 
  多播委托广泛用于事件处理中。  事件源对象将事件通知发送到已注册接收该事件的接收方对象。  若要注册一个事件,接收方需要创建用于处理该事件的方法,然后为该方法创建委托并将委托传递到事件源。  事件发生时,源调用委托。  然后,委托将对接收方调用事件处理方法,从而提供事件数据。  给定事件的委托类型由事件源确定。   

 

传送门

  《C# 知识回顾 - 序列化

  《C# 知识回顾 - 表达式树 Expression Trees》

  《C# 知识回顾 - 特性 Attribute》、《剖析 AssemblyInfo.cs - 了解常用的特性 Attribute》

 


【参考】微软官方文档







原标题:[C#] C# 知识回顾

关键词:C#

C#
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

中东市场选品禁忌,这些商品千万别卖!:https://www.ikjzd.com/articles/1661247166783713281
98年普通打工人,如何从0做到5万美金独立站:https://www.ikjzd.com/articles/1661247658615578625
快来了解!继30多国之后,又有这些国家即将使用人民币结算:https://www.ikjzd.com/articles/1661264599870808066
探索2023年海外网红营销合作方式:提升品牌曝光度的创新策略:https://www.ikjzd.com/articles/1661267218073415681
出海访谈专栏|卖家必知的海外仓的一些事儿,看完这篇就够了!:https://www.ikjzd.com/articles/1661274949299761154
让中小外贸企业率先用上AI:外贸生意智能工作台OKKI产品升级:https://www.ikjzd.com/articles/1661283170520866817
皇帝的皇宫=:https://www.vstour.cn/a/363188.html
海南岛琼海市旅游景点 琼海市的旅游景点:https://www.vstour.cn/a/363189.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流