【问题标题】:How to add another action to an action in C#?如何向 C# 中的操作添加另一个操作?
【发布时间】:2021-04-22 09:03:23
【问题描述】:

为什么这段代码只打印“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();

【问题讨论】:

    标签: c# delegates


    【解决方案1】:

    委托是不可变的。 += 运算符创建一个 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以引用新组合的委托...然后忽略它。

    相反,您需要返回组合委托(因此将add 更改为Func&lt;Action, Action&gt;),然后在调用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();
    

    【讨论】:

    • 那么,相比之下,这就像将“int”传递给函数和内部,为该“int”添加一些值?无论如何,所有这些都对我有所帮助,并且一如既往,我被困在最简单的事情上。谢谢!
    • @krokots:是的,没错。
    【解决方案2】:

    您可能知道,A += B 只是 A = A + B 的简写,所以您的 add 代表实际上只是:

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

    + 创建组合委托a + () =&gt; MessageLog.Message("C"),然后= 将其分配回a。请注意您是如何重新分配参数a,现在应该很清楚这个doesn't change the variable that is passed in (act) at all

    除了返回组合委托外,还可以通过引用传递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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多