问题描述
我有一个简单的事件:
public class ClassA
{
public event Func<string, int> Ev;
public int Do(string l)
{
return Ev(l);
}
}
还有两种方法:
static int Display(string k)
{
return k.Length;
}
static int Display_2(string k)
{
return k.Length*10;
}
我正在注册这个活动:
ClassA a = new ClassA();
a.Ev += Display;
a.Ev += Display_2;
现在,我正在执行:
Console.WriteLine(a.Do("aaa"));
输出:
什么???
他在调用列表中有 2 个方法!它确实运行了它们,但为什么它只显示last注册的结果?
he has in invocation list 2 methods ! it did run them , but why does it shows only the result from the last registration ?
3"
的结果到哪里去了?(第一次调用)?(虽然 display
+display_2
都被执行了......我没想到 console.write
会遍历结果.但也没想到他会决定展示哪个.)
Where does the result of "3"
has gone ? ( the first invocation ) ? ( although both display
+display_2
was executed... I didn't expect console.write
to iterate through results . but also didn't expect him to decide which to show.)
推荐答案
这里涉及三个方面:
- 活动的实施
- 委托组合的行为
- 调用其调用列表中有多个条目的委托的行为
对于第 1 点,您有一个 field-like 事件.C# 4 规范的第 10.8.1 节给出了一个示例,并指出:
For point 1, you have a field-like event. Section 10.8.1 of the C# 4 spec gives an example, and states that:
在 Button
类的声明之外,Click
成员只能在 +=
的左侧使用,并且-=
运算符,如
Outside the declaration of the
Button
class, theClick
member can be used only on the left-hand saide of the+=
and-=
operators, as in
b.Click += new EventHandler(...);
将委托附加到 Click
事件的调用列表
which appends a delegate to the invocation list of the Click
event
(强调我的).该规范还明确指出,类字段事件会创建一个委托字段,该字段用于在类内进行调用.
(emphasis mine). The spec also makes it clear that a field-like event creates a delegate field, which is used from within the class for invocation.
更一般地说(第 2 点),C# 4 规范的第 7.8.4 节讨论了通过 +
和 +=
进行委托组合:
More generally (point 2), section 7.8.4 of the C# 4 spec talks about delegate combination via +
and +=
:
委托组合.每个委托类型都隐式提供以下预定义运算符,其中 D
是委托类型:
Delegate combination. Every delegate type implicitly provides the following predefined operator, where
D
is the delegate type:
D operator +(D x, D y)
二进制+
操作符在两个操作数都属于某个委托类型D
时执行委托组合.[...跳过 x
或 y
为空的位 ...] 否则,操作的结果是一个新的委托,当被调用时,调用第一个操作数,然后调用第二个操作数.
The binary +
operato performs delegate combination when both operands are of some delegate type D
. [... skip bits where x
or y
are null ...] Otherwise, the result of the operation is a new delegate that, when invoked, invokes the first operand and then invokes the second operand.
(再次强调我的.)
最后,第 3 点 - 事件调用和返回值.C# 规范第 15.4 节指出:
Finally, point 3 - event invocation and return values. Section 15.4 of the C# spec states:
如果委托调用包含输出参数或返回值,则它们的最终值将来自列表中最后一个委托的调用.
If the delegate invocation includes output parameters or a return value, their final value will come from the invocation of the last delegate in the list.
更一般地说,它取决于事件的实现.如果您使用使用正常"的事件实现.委托组合/移除步骤,一切有保障.如果你开始编写一个做疯狂事情的自定义实现,那就是另一回事了.
More generally, it depends on the event implementation. If you use an event implementation which uses the "normal" delegate combination/removal steps, everything is guaranteed. If you start writing a custom implementation which does crazy things, that's a different matter.
这篇关于C# 中的多播委托奇怪行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!