写在前面

为什么会突然想说说委托?原因吗,起于一个同事的想法,昨天下班的路上一直在想这个问题,如果给委托注册多个方法,会不会都执行呢?为了一探究性,就弄了个demo研究下。

+=

大家都知道委托都继承自System.MulticastDelegate,而System.MulticastDelegate又继承自System.Delegate,可以通过+=为委托注册多个方法。那么他们是否都执行了呢?执行的结果又是怎样的呢?有返回值和没返回值的是否结果是否一样?那就试着说说+=都干了哪些事?

测试代码

 namespace Wolfy.DelegateDemo
{
public delegate void ShowMsg(string msg);
public delegate int MathOperation(int a, int b);
class Program
{
static ShowMsg showMsg;
static MathOperation mathOperation;
static void Main(string[] args)
{
showMsg += ShowHello;
showMsg += ShowHello1;
showMsg("大家新年好啊");
mathOperation += Add;
mathOperation += Multiply;
int result = mathOperation(, );
Console.WriteLine(result.ToString());
Console.Read();
}
static void ShowHello(string msg)
{
Console.WriteLine("哈喽:" + msg);
}
static void ShowHello1(string msg)
{
Console.WriteLine("哈喽1:" + msg);
}
static int Add(int a, int b)
{
return a + b;
}
static int Multiply(int a, int b)
{
return a * b;
}
}
}

你可以猜猜运行结果,如下图:

可以看到没有返回值的都输出了,有返回值的只输出了Mutiply的结果,那么+=内部做了哪些事?可以看一下反编译的代码:

 using System;
namespace Wolfy.DelegateDemo
{
internal class Program
{
private static ShowMsg showMsg;
private static MathOperation mathOperation;
private static void Main(string[] args)
{
Program.showMsg = (ShowMsg)Delegate.Combine(Program.showMsg, new ShowMsg(Program.ShowHello));
Program.showMsg = (ShowMsg)Delegate.Combine(Program.showMsg, new ShowMsg(Program.ShowHello1));
Program.showMsg("大家新年好啊");
Program.mathOperation = (MathOperation)Delegate.Combine(Program.mathOperation, new MathOperation(Program.Add));
Program.mathOperation = (MathOperation)Delegate.Combine(Program.mathOperation, new MathOperation(Program.Multiply));
Console.WriteLine(Program.mathOperation(, ).ToString());
Console.Read();
}
private static void ShowHello(string msg)
{
Console.WriteLine("哈喽:" + msg);
}
private static void ShowHello1(string msg)
{
Console.WriteLine("哈喽1:" + msg);
}
private static int Add(int a, int b)
{
return a + b;
}
private static int Multiply(int a, int b)
{
return a * b;
}
}
}

通过上面的代码可以看出+=内部是通过委托的 Combine静态方法将委托进行组合的,可以看一下委托的这个静态方法是如何实现的。

可以看到最终调用CombineImpl这个方法,这个方法内部很奇怪:

并没有我们想看到的代码,那这个方法是干嘛用的啊?

MSDN的解释

Concatenates the invocation lists of the specified multicast (combinable) delegate and the current multicast (combinable) delegate.

大概意思就是:将当前的委托加入到指定的多播委托集合中。

绕了一圈那么有返回值的委托,到底执行了么?那也只能通过调试来看看了。(绕了一圈,又回到了编辑器,唉)

继续F11你会发现确实进入了Add方法

也确实执行了,但在遍历多播委托集合的时候,将之前的值给覆盖了。

那么现在可以得出这样的结论了:无返回值的委托,你给它注册多少个方法,它就执行多少个方法,而有返回值的委托,同样注册多少个方法就执行多少个方法,但返回的是最后一个方法的返回值。

-=

既然说了+=,那么作为收拾烂摊子的-=也不得不说。在项目中使用了+=就要使用-=来释放。那它内部做了哪些事?同样使用上面的代码,在输出结果后,使用-=来释放资源。

可以看出,使用-=内部是调用了委托的Remove静态方法。

使用-=最终是将委托置为null,为null另一个意思就是空引用,这样就可以等待垃圾回收器进行回收了。

总结

这个问题虽然很基础,一个同事当时问了,就给他说了一下,在下班的路上一直在想,内部是如何实现的?就试着通过反编译的方式一探究竟。但貌似CombineImpl这个方法,给的结果不太满意。没看到具体的实现。希望对你有所帮助!

[C#基础]说说委托+=和-=的那些事的更多相关文章

  1. C#基础系列——委托和设计模式(二)

    前言:前篇 C#基础系列——委托实现简单设计模式 简单介绍了下委托的定义及简单用法.这篇打算从设计模式的角度去解析下委托的使用.我们知道使用委托可以实现对象行为(方法)的动态绑定,从而提高设计的灵活性 ...

  2. [.net 面向对象编程基础] (21) 委托

    [.net 面向对象编程基础] (20)  委托 上节在讲到LINQ的匿名方法中说到了委托,不过比较简单,没了解清楚没关系,这节中会详细说明委托. 1. 什么是委托? 学习委托,我想说,学会了就感觉简 ...

  3. 转载 【.NET基础】--委托、事件、线程(2) https://www.cnblogs.com/chengzish/p/4569912.html

    [.NET基础]--委托.事件.线程(2)   本文介绍event的使用以及原理,本文接上一篇文章的Demo继续[下载上一篇Demo] 上一篇我们在类(dg_SayHi.cs)里面定义代理了4个Del ...

  4. 转载 【.NET基础】--委托、事件、线程(1) https://www.cnblogs.com/chengzish/p/4559268.html

    [.NET基础]--委托.事件.线程(1)   1,委托 是存放方法的指针的清单,也就是装方法的容器 A, 新建winform项目[01委托],项目中添加dg_SayHi.cs 委托类 用于存储方法 ...

  5. C#基础系列——委托实现简单设计模式

    前言:上一篇介绍了下多线程的相关知识:C#基础系列——多线程的常见用法详解,里面就提到了委托变量.这篇简单介绍下委托的使用.当然啦,园子里面很多介绍委托的文章都会说道:委托和事件的概念就像一道坎,过了 ...

  6. 【.NET基础】--委托、事件、线程(3)

    之前的两篇文章我们了解了委托和事件,本文我们看一下线程. 1,一个窗体程序,默认拥有一个线程(相当于一个商店里面,只有一个店员),这个默认的线程叫做 UI线程/主线程. 2,进程和线程的关系: A,进 ...

  7. 转载 【.NET基础】--委托、事件、线程(3)

      之前的两篇文章我们了解了委托和事件,本文我们看一下线程. 1,一个窗体程序,默认拥有一个线程(相当于一个商店里面,只有一个店员),这个默认的线程叫做 UI线程/主线程. 2,进程和线程的关系: A ...

  8. C#基础之委托

    委托常常和事件在一起使用,可以理解委托是方法的容器,事件则是委托的另一种表现形式.委托和事件虽然写得还比较多,不过也只是用的熟练而已,趁周末没课好好巩固下基础,一点一点积累吧. 1.一个简单的小例子 ...

  9. C#基础篇——委托

    前言 在本章中,主要是借机这个C#基础篇的系列整理过去的学习笔记.归纳总结并更加理解透彻. 在.Net开发中,我们经常会遇到并使用过委托,如果能灵活的掌握并加以使用会使你在编程中游刃有余,然后对于很多 ...

随机推荐

  1. 在matlab2015b中配置vlfeat-0.9.18

    参考链接: 1.http://cnyubin.com/?p=85                2.http://www.cnblogs.com/woshitianma/p/3872939.html ...

  2. MyDiary,《你的名字。》同款日记应用

    新海城导演的新作<你的名字.>已经于 12 月 2 日在国内公映,这部评价极高的动画电影无论在剧情还是美术上都相当出色,是一部不容错过的好片.如果你还没有看过,赶快趁着还没下档买票去看看吧 ...

  3. hdu1710(二叉树的历遍)

    /* Binary Tree Traversals Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...

  4. CORDIC原理与FPGA实现(2)

    CORDIC算法实现极坐标(polar)到直角坐标系(Cartesian)的变换. 1: function [horizonal,vertical]=polar2car(mag, pha); 2: x ...

  5. uva 558 tree(不忍吐槽的题目名)——yhx

    You are to determine the value of the leaf node in a given binary tree that is the terminal node of ...

  6. Linux下的C之2048

    #include <stdio.h> #include <stdlib.h> #include <curses.h> #include <time.h> ...

  7. cri-o 与 cni的集成分析

    // 创建pod时,network的设置 1.// cri-o/server/sandbox.go // RunPodSandbox creates and runs a pod-level sand ...

  8. Vim tips

    1.光标移动: (1).NG -> 移动到第N行,或者使用:N (2).gg -> 移动到第一行 (3).G -> 移动到最后一行 (4).单词移动: w -> 移动到下一个单 ...

  9. 【ASP.NET 进阶】定时执行任务

    原理:利用全局应用程序类 Global.asax 和 System.Timers.Timer  类定时处理任务. 示例效果图: 其 Global.asax 类代码如下: using System; u ...

  10. Debian系统网卡调试出问题,无线网卡提示device not managed如何解决?

    参考文章:<How to fix Wired Network interface “Device not managed” error in Debian or Kali Linux?> ...