委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托

在"委托、Lambda表达式、事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性"中,反编译委托,发现委托都是多播委托。

既然委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链, 它是怎样形成的?来看下面的例子:

namespace ConsoleApplication3
{
    internal delegate void MySayDel(string msg);
    class Program
    {
        static void Main(string[] args)
        {
            MySayDel del = SayHello;
            del = (MySayDel)Delegate.Combine(del, new MySayDel(SayNice)); //等同于:del += SayNice;
            del += SayOk;
            del("darren");
        }

        static void SayHello(string msg)
        {
            Console.WriteLine("hello " + msg);
        }

        static void SayNice(string msg)
        {
            Console.WriteLine("nice " + msg);
        }

        static void SayOk(string msg)
        {
            Console.WriteLine("ok " + msg);
        }
    }
}


最后,调用委托执行方法,最先注册的方法最先执行。"+="是一种"语法糖",内部其实调用了Delegate的静态方法Combine,形成委托链,再把委托链赋给委托变量。大致如下:

→当执行MySayDel del = SayHello;

→当执行del = (MySayDel)Delegate.Combine(del, new MySayDel(SayNice)),在托管堆上又创建MySayDel委托实例指向SayNice方法,接着复制原先的、指向SayHello方法的委托实例,2个委托实例形成委托链,即蓝色区域部分,栈上的委托变量del指向委托链。

以上,委托的返回类型是void,当调用委托的时候,依次执行委托链的方法。可是,如果委托的返回类型不是void,会不会依次执行委托链的方法呢?

    internal delegate int MyCalulateDel(int val1, int val2);
    class Program
    {
        static void Main(string[] args)
        {
            MyCalulateDel del = Add;
            del += Sub;
            Console.WriteLine(del.Invoke(20, 10));
        }

        static int Add(int val1, int val2)
        {
            return val1 + val2;
        }

        static int Sub(int val1, int val2)
        {
            return val1 - val2;
        }
    }



以上,当调用委托不会依次执行委托链方法,而是会执行最后注册的方法。

如果我们想得到所有委托方法的返回结果,该如何做到呢?
--委托为我们提供了一个GetInvocationList的实例方法,可以获取所有委托。

    internal delegate int MyCalulateDel(int val1, int val2);
    class Program
    {
        static void Main(string[] args)
        {
            MyCalulateDel del = Add;
            del += Sub;

            var result = GetResultForEachDel(del, 20, 10);
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }
        }

        static List<int> GetResultForEachDel(MyCalulateDel del, int val1, int val2)
        {
            List<int> result = new List<int>();
            foreach (MyCalulateDel item in del.GetInvocationList())
            {
                result.Add(item.Invoke(val1, val2));
            }
            return result;
        }

        static int Add(int val1, int val2)
        {
            return val1 + val2;
        }

        static int Sub(int val1, int val2)
        {
            return val1 - val2;
        }
    }



以上,通过GetInvocationList实例方法获取所有的委托,然后分别调用所有的委托方法。

总结:
○ 如果委托的返回类型是void,并且形成委托链,只要调用委托就会依次执行委托链方法。
○ 如果委托的返回类型不是void,并且形成委托链,可以使用委托的GetInvocationList实例方法获取所有委托,然后遍历这些委托依次调用委托得到所有返回类型。

“委托、Lambda表达式、事件系列”包括:

委托、Lambda表达式、事件系列01,委托是什么,委托的基本用法,委托的Method和Target属性

委托、Lambda表达式、事件系列02,什么时候该用委托

委托、Lambda表达式、事件系列03,从委托到Lamda表达式

委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托

时间: 2024-10-12 15:10:36

委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托的相关文章

C# 委托,Lambda表达式,事件

本文章参考sikiC#高级篇,转载请注明出处. 什么是委托 如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托与使用 声明委托有四种方式.一种是原生的,另外三种是C#为了方便给我们封装好的. 四种声明方式分别为delegate, Action, Func, 在C#中使用一个类分为两个阶段,首先定义这个类,告诉编译器这个类由什么字段和方法组成,然后使用这个类实例化对象.在我们使用委托的时候,也需要经过这两个阶段,首先定义委托,告诉编

个人总结:匿名委托+内置委托+Lambda表达式

匿名委托+内置委托+Lambda表达式 概要 在实际开发中,项目开发框架不同,用到的技术是不一样的,这里总结一下用Linq开发,ORM之EF开发会大量使用的Lambda表达式; 正文 之前提过.Net有一套扩展在IEumberable<T>泛型接口的扩展方法,本文是从这个基础继续总结; 1.void Action<in T>: 先拿一个ForEach()来讲: public void ForEach(Action<T> action); 这个Action<T>

委托-异步调用-泛型委托-匿名方法-Lambda表达式-事件

1. 委托 From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html 类是对象的抽象,而委托则可以看成是函数的抽象.一个委托代表了具有相同参数列表和返回值的所有函数. [csharp] view plaincopy class Program { delegate int CalculateDelegate(int a, int b); int add(int a, int b) { return a + b; } s

委托 lambda表达式浅显理解

方法不能跟变量一样当参数传递,怎么办,C#定义了委托,就可以把方法当变量一样传递了,为了简单,匿名方法传递,省得再声明方法了:再简单,lambda表达式传递,比匿名方法更直观. public delegate int delegateArithmetic(int a, int b); //委托作为参数,方法传递给委托 public int result(int x,int y,delegateArithmetic delAri) { return delAri(x, y); } public i

委托、Lambda表达式、事件系列07,使用EventHandler委托

谈到事件注册,EventHandler是最常用的. EventHandler是一个委托,接收2个形参.sender是指事件的发起者,e代表事件参数. □ 使用EventHandler实现猜拳游戏 使用EventHandler实现一个猜拳游戏,每次出拳,出剪刀.石头.布这三者的其中一种. 首先抽象出一个被观察者,其中提供了事件,提供了执行事件的方法. public class FistGame { public string FistName { get; set; } public event

委托、Lambda表达式、事件系列05,Action委托与闭包

来看使用Action委托的一个实例: static void Main(string[] args) { int i = 0; Action a = () => i++; a(); a(); Console.WriteLine(i); } 结果是期望能的2.但令人好奇的是:栈上的变量i是如何传递给Action委托的? 反编译进行查看,首先看Main方法对应的IL代码: 再看c_DisplayClass1的IL代码: 从中可以看出:→在托管堆上创建了一个名为c_DisplayClass1的实例→把

委托、Lambda表达式、事件系列06,使用Action实现观察者模式

在"实现观察者模式(Observer Pattern)的2种方式"中,曾经通过接口的方式.委托与事件的方式实现过观察者模式.本篇体验使用Action实现此模式. 就举一个足球场上的例子,当裁判吹响终场哨,胜队庆祝,失败队落寞.把裁判看作是被观察者,比赛中的两队看作是观察者. 裁判作为被观察者需要提供一个Action委托供观察者方法注册. public class Referee { public Action DoSth; public void ISayGameOver() { Co

委托,匿名函数和lambda表达式

很早之前就接触到了委托,但是一直对他用的不是太多,主要是本人是菜鸟,能写的比较高级的代码确实不多,但是最近在看MSDN微软的类库的时候,发现了微软的类库好多都用到了委托,于是决定好好的研究研究,加深一下自己对他的印象,顺便把自己的感悟和想法写出来,以便自己能有更深的理解,由于本人水平有限,也欢迎大家多多探讨,有问题大家一起解决一起进步. MSDN上面对委托的定义是:delegate 是表示对具有特定参数列表和返回类型的方法的引用的类型.在我看来委托的特性主要在: 1.把一个方法当做一个参数传递给

C#匿名委托,匿名函数,lambda表达式

一.类型.变量.实例之间的关系. 类型>变量>实例 类型可以创建变量,实体类可以创建实例,实例可以存储在变量里. 二.委托使用过程: 1.定义委托(写好签名): 2.创建委托变量: 3.在委托变量里放函数(相同的签名). 事件:用预先定义好的委托(EventHandle)的定义的变量(接收两个参数). 窗体里自带一个委托变量:我们做的就是给这个变量追加函数. 给窗体Load事件添加一个函数 public partial class Form1 : Form { public Form1() {