翼度科技»论坛 编程开发 .net 查看内容

Learning hard C#学习笔记——读书笔记 06

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
之前的大部分内容,其实都是面向对象语言的共性,而这次的委托是 C# 特有的内容

1.委托的定义


C# 中的委托可以理解为函数的包装,它使得 C# 中的函数可以作为参数来传递(类似于JavaScript中的高级函数),作用上相当于C++中的函数指针,C++用函数指针获取函数的入口地址,然后通过这个指针实现对函数的操作
委托的定义和方法的定义类似,只是在前面多了一个delegate关键字
  1. public delegate void MyDelegate(int para1,string para2);
复制代码
委托包装方法的条件

  • 方法的签名必须和委托一致,方法签名包括参数的个数、类型、顺序
  • 方法的返回类型要和委托一致(方法的返回类型不属于方法签名的一部分)
简单来说,如图所示:

简单来说,就是我们将MyMethod()方法委托给了MyDelegate()去执行了

2.委托的使用

  1. class Program {
  2.     // 1.使用delegate定义委托使用
  3.     delegate void MyDelegate(int a, int b);
  4.     public static void Main(string[] args) {
  5.         // 2.声明委托变量d
  6.         MyDelegate d;
  7.         // 3.实例化委托变量d
  8.         d = new MyDelegate(new Program().add);
  9.         // 4.委托作为参数进行传递
  10.         MyMethod(d);
  11.         Console.Read();
  12.     }
  13.     public void add(int a, int b) {
  14.         int c = a + b;
  15.         Console.WriteLine("最后的结果为:{0}",c);
  16.     }
  17.     private static void MyMethod(MyDelegate mydelegate) {
  18.         // 5.在方法中调用委托
  19.         mydelegate(1, 2);
  20.     }
  21. }
复制代码

委托使用的注意点:

  • 委托实例化传递的参数,必须和委托定义相同,即方法的返回类型和参数个数、参数类型都碧血和委托相同,并且,传递的是方法名(不带括号)
  • 委托的调用,与方法调用类似,传递的实际参数个数必须与委托定义一致
  • 委托是方法包装类型,所以委托的调用实际上是对包装的方法的调用

3.为什么引入委托


我们先看一个没有委托的写法
我们可以发现,没有委托,如果我们打招呼的方式多了起来,则Greet中的switch case语句要一直写下去,根据“开闭原则”(对扩展开发,对修改关闭),我们是不建议这样去写的
  1. class Program {
  2.     public static void Main(string[] args) {
  3.         Program p = new Program();
  4.         p.Greet("李广", "zh-cn");
  5.     }
  6.     public void Greet(string name,string language) {
  7.         switch (language) {
  8.             case "zh-cn":
  9.                 ChineseGreeting(name);
  10.                 break;
  11.             case "en-us":
  12.                 EnlishGreeting(name);
  13.                 break;
  14.             default:
  15.                 EnlishGreeting(name);
  16.                 break;
  17.         }
  18.     }
  19.     // 1.中国人打招呼的方式
  20.     public void ChineseGreeting(string name) {
  21.         Console.WriteLine("你好"+name);
  22.     }
  23.     public void EnlishGreeting(string name) {
  24.         Console.WriteLine("Hello"+name);
  25.     }
  26. }
复制代码
而如果我们使用了委托,我们可以不破坏原有的代码内容,只需要在后面继续添加新的打招呼方法就可以,这样提高了程序的可扩展性
  1. class Program {
  2.     public delegate void GreetDelegate(string name);
  3.     public static void Main(string[] args) {
  4.         Program p = new Program();
  5.         p.Greet("李广", p.EnlishGreeting);
  6.         p.Greet("李广", p.ChineseGreeting);
  7.     }
  8.     public void Greet(string name, GreetDelegate callback) {
  9.         callback(name);
  10.     }
  11.     // 1.中国人打招呼的方式
  12.     public void ChineseGreeting(string name) {
  13.         Console.WriteLine("你好"+name);
  14.     }
  15.     public void EnlishGreeting(string name) {
  16.         Console.WriteLine("Hello"+name);
  17.     }
  18. }
复制代码
4.委托的本质

  1. class Program {
  2.     public delegate void DelegateTest(int parm);
  3.     static void Main(string[] args) {
  4.         Console.WriteLine("调用");
  5.     }
  6. }
复制代码

用以上的代码来反编译一下,我们发现DelegateTest委托类型使用了.class关键字进行标识,所以 C# 编译器会把我们定义的委托类型,编译成如下的类类型

IAsyncResult和EndInvoke 这两个方法是异步方法


我们可以对Invoke进行显式调用,最后,我们可以清楚的看到,委托是类类型

最后我们发现,其本质也就是调用了Invoke方法来执行对应的方法


总结:
委托的本质,其实就是一个类,这个类中一共有四个方法

  • 构造方法
  • Invoke()调用函数参数的方法
  • 一个异步获取方法返回值的方法
  • 一个异步执行参数方法的方法


5.委托链


前面都是委托封装一个方法的情况,即一个委托只为一个方法服务,但是也有一个委托为多个方法服务的情况,C# 中把封装多个方法的委托称为委托链或多路广播委托


5.1 委托链的使用

委托链其实就是委托类型,只是委托链将多个委托链接在一起了而已
向委托链中添加委托是使用 + ,那么移除委托就是使用 - ,委托链中移除委托后,仍然可以将委托移动到其它委托链中
  1. class Program
  2. {
  3.     public delegate void DelegateTest();
  4.     static void Main(string[] args) {
  5.         // 1.委托1
  6.         DelegateTest delegateMethod1 = new DelegateTest(Program.method1);
  7.         // 2.委托2
  8.         DelegateTest delegateMethod2 = new DelegateTest(new Program().method2);
  9.         // 3.定义委托链
  10.         DelegateTest delegateChain = null;
  11.         // 4.向委托链中添加委托
  12.         delegateChain += delegateMethod1;
  13.         delegateChain += delegateMethod2;
  14.         delegateChain();
  15.         Console.Read();
  16.     }
  17.     private static void method1() {
  18.         Console.WriteLine("这是静态方法");
  19.     }
  20.   
  21.     private  void method2() { Console.WriteLine("这是实例方法"); }
  22. }
复制代码


来源:https://www.cnblogs.com/trueasureyuki/archive/2023/07/19/17563994.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具