多播委托C#中的奇怪行为?

Roy*_*mir 0 .net c# delegates

我有这个简单的事件:

public class ClassA
{
    public event Func<string, int> Ev;
    public int Do(string l)
    {
        return Ev(l);
    }
}
Run Code Online (Sandbox Code Playgroud)

和2方法:

  static int Display(string k)
        {
            return k.Length;
        }

  static int Display_2(string k)
        {
            return k.Length*10;
        }
Run Code Online (Sandbox Code Playgroud)

我正在注册这个活动:

 ClassA a = new ClassA();
 a.Ev += Display;
 a.Ev += Display_2;
Run Code Online (Sandbox Code Playgroud)

现在,我正在执行:

   Console.WriteLine(a.Do("aaa")); 
Run Code Online (Sandbox Code Playgroud)

输出 :

在此输入图像描述

什么 ???

  • 他在调用列表中有2种方法!它确实运行了它们,但为什么它只显示上次注册的结果?

  • 结果在哪里"3"消失了?(第一次调用)?(虽然两个display+都display_2被执行了......我没想到console.write会迭代结果.但也没想到他决定要显示哪个.)

编辑:

在此输入图像描述

Jon*_*eet 6

这里有三个方面:

  1. 该事件的实施
  2. 委托组合的行为
  3. 调用其调用列表具有多个条目的委托的行为

对于第1点,您有一个类似字段的事件.C#4规范的第10.8.1节给出了一个例子,并说明:

Button类的声明之外,该Click成员只能在+=-=运算符的左侧使用,如

b.Click += new EventHandler(...);
Run Code Online (Sandbox Code Playgroud)

它将一个委托附加到Click事件的调用列表

(强调我的).该规范还清楚地表明,类似字段的事件会创建一个委托字段,该字段类中用于调用.

更一般地说(第2点),C#4规范的第7.8.4节谈到代表组合通过++=:

代表组合.每个委托类型隐式提供以下预定义运算符,其中D是委托类型:

D operator +(D x, D y)
Run Code Online (Sandbox Code Playgroud)

+当两个操作数都是某种委托类型时,二元operato执行委托组合D.[...跳过其中xy为空的位...]否则,操作的结果是一个新的委托,当被调用时,调用第一个操作数然后调用第二个操作数.

(再次强调我的.)

最后,第3点 - 事件调用和返回值.C#规范的第15.4节规定:

如果委托调用包括输出参数或返回值,则它们的最终值将来自列表中最后一个委托的调用.

更一般地说,它取决于事件的实现.如果您使用使用"正常"委托组合/删除步骤的事件实现,则一切都得到保证.如果你开始编写一个做疯狂事情的​​自定义实现,那就不一样了.


Hen*_*man 5

调用多播非void委托会返回已执行的最后一个处理程序的值.

你几乎无法控制谁是第一个或最后一个.这是一个糟糕的系统使用.

这就是大多数活动和代表回归的原因void.

  • 使用类似字段的事件,将按订阅顺序调用委托 - 它们都是明确定义的.对于更一般的事件,当然不是这样 - 不能保证一个事件会提供合理的`add` /`remove`实现......但是我会非常惊讶地看到一个事件没有.当然,调用不是你可以用*event*做的一部分(在C#中)...... (2认同)