写在前面

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

    一.简介 Watchdog主要用于监视系统的运行,Linux内核不仅为各种不同类型的watchdog硬件电路提供了驱动,还提供了一个基于定时器的纯软件watchdog驱动. 驱动源码位于内核源码树dr ...

  2. DataGridView合并单元格

    昨天一个同事问我DataGridView单元格合并的问题,一开始按照我的设想是算出两个单元格的Rectangle,然后直接使用e.Graphics.FillRectangle(backColorBru ...

  3. eclipse在Ubuntu 13.04下的安装过程及问题小记

    一.eclipse安装过程 首先确保在安装eclipse之前已经安装好Java虚拟机 1. eclipse官网下载压缩包 下载地址:http://www.eclipse.org/downloads/? ...

  4. 使用reportNG替换testNG的默认报告

    关于reportng的官网介绍:http://reportng.uncommons.org/ 1.下载reportNG的jar包:http://pan.baidu.com/s/1hq5znLU 2.r ...

  5. POJ 1442 Black Box -优先队列

    优先队列..刚开始用蠢办法,经过一个vector容器中转,这么一来一回这么多趟,肯定超时啊. 超时代码如下: #include <iostream> #include <cstdio ...

  6. Android学习----自适应国际化语言

    [前言] 自适应的知识与编程无关,关键在于配置文件的修改.自适应的内容包括:语言.屏幕.平台.今天就来说一下如何自适应国际化言. internationalization (国际化)简称:i18n,因 ...

  7. 第51课 C++对象模型分析(下)

    1. 单继承对象模型 (1)单一继承 [编程实验]继承对象模型初探 #include <iostream> using namespace std; class Demo { protec ...

  8. java 11-8 在大串中查找小串的案例

    1.统计大串中小串出现的次数 举例: 在字符串"woaijavawozhenaijavawozhendeaijavawozhendehenaijavaxinbuxinwoaijavagun& ...

  9. javascript中的时间处理

    var myDate = new Date(); myDate.getYear(); //获取当前年份(2位) myDate.getFullYear(); //获取完整的年份(4位,1970-???? ...

  10. iOS获取窗口当前显示的控制器

    解决类似网易新闻客户端收到新闻推送后,弹出一个UIAlert,然后跳转到新闻详情页面这种需求 1.提供一个UIView的分类方法,这个方法通过响应者链条获取view所在的控制器 - (UIViewCo ...