如何在 C# 中向一个动作添加另一个动作?

How to add another action to an action in C#?

为什么这段代码只打印“A”和“B”,而不打印“C”?

Action act = null;
act += () => MessageLog.Message("A");
act += () => MessageLog.Message("B");
Action<Action> add = a => a += () => MessageLog.Message("C");
add(act);
act.Invoke();

委托是不可变的。 += 运算符创建一个 new 委托,其中包含一个调用列表,该列表由左侧的调用列表和运算符右侧的调用列表组成。然后它将对该委托的引用存储在左侧的变量中。所以

act += () => MessageLog.Message("A");

等同于

act = act + (Action) (() => MessageLog.Message("A"));

这又等同于:

act = (Action) Delegate.Combine(act, (Action) (() => MessageLog.Message("A"));

那么,现在我们可以请您的 add 代表了。这个 lambda 表达式:

a => a += () => MessageLog.Message("C");

...修改参数a以引用新组合的委托...然后忽略它。

相反,您需要 return 组合委托(因此将 add 更改为 Func<Action, Action>),然后使用 return 调用时的值 add:

Action act = null;
act += () => MessageLog.Message("A");
act += () => MessageLog.Message("B");
Func<Action, Action> add = a => a + () => MessageLog.Message("C");
act = add(act);
act.Invoke();

您可能知道,A += B 只是 A = A + B 的 shorthand,所以您的 add 委托实际上只是:

a => a = a + () => MessageLog.Message("C")

+ 创建组合委托 a + () => MessageLog.Message("C")= 将其分配回 a。请注意您刚刚如何重新分配参数 a,现在应该清楚这个 .

除了返回组合委托外,您还可以通过引用传递act

delegate void ByRefAction<T>(ref T parameter);

...

    Action act = null;
    act += () => Console.WriteLine("A");
    act += () => Console.WriteLine("B");
    ByRefAction<Action> add = (ref Action a) => a += () => Console.WriteLine("C");
    add(ref act);
    act.Invoke();