【问题标题】:Is there a way to generalise Action and Action<T>?有没有办法概括 Action 和 Action<T>?
【发布时间】:2016-05-27 11:55:36
【问题描述】:

所以我有一个扩展方法,允许我在执行操作时记录一些内容。实现是这样的:

public static Action Log(this Action action, string log) {
    return (() => {
        Console.WriteLine(log);
        action();

    });
}

但我希望该操作也可以是 Action&lt;T&gt;。有没有办法概括这一点,以便 log 被记录,但它不会更改操作的签名?

或者我需要两种方法,一种用于Action,一种用于Action&lt;T&gt;

【问题讨论】:

    标签: c# generics action extension-methods


    【解决方案1】:

    您需要单独的方法,但您可以根据另一个实现一个以减少代码重复:

    鉴于您现有的Log(Action action, string log),您可以添加:

    public static Action<T> Log<T>(this Action<T> action, string log) {
        return t => Log(() => action(t), log);
    }
    

    或者反过来:

    public static Action<T> Log(this Action<T> action, string log) {
        return t => {
            Console.WriteLine(log);
            action(t);
        });
    }
    
    public static Action Log(this Action action, string log) {
        return () => Log<object>(t => action(), log);
    }
    

    【讨论】:

      【解决方案2】:

      您将需要两种方法,因为在这种情况下ActionAction&lt;T&gt; 彼此不兼容。

      如果Action 实际上是Action&lt;void&gt; 来启用此行为会很有用,但事实并非如此。

      【讨论】:

      • 是的,Swift 允许这样做,因为Void 本身就是一种数据类型。我想知道 C# 是否也允许这样做。
      【解决方案3】:

      您可以使用Delegate 类型并为您的操作提供参数param object[],如下所示:

      public static Action Log(this Delegate action, string log, params object[] args)
      {
          return () =>
          {
              Console.WriteLine(log);
              action.DynamicInvoke(args);
          };
      }
      

      你可以这样使用这个扩展:

      Action<int> testAction = i => Console.WriteLine($"Test: {i}");
      testAction.Log("Logging", 42).Invoke();
      

      这会导致以下输出:

      Logging
      Test: 42
      

      【讨论】:

      • 哦,我的印象是 OP 希望 Log&lt;T&gt; 返回 Action&lt;T&gt;(这意味着操作的参数不会传递给 Log)——但 OP 没有t 指定。你的解释可能是对的。
      • 是的,这不是我的想法,我想存储生成的Action 并稍后调用它。但这很好+1
      • 赞成,因为这是一个有趣的解决方案,但它涉及某种“动态模式”。由于我们使用的是 C#,这是一种静态类型语言,所以 @hvd 解决方案要好得多。它也与您在 .NET 基础框架和大多数可用的库中找到的内容一致。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 2012-03-04
      • 2018-07-15
      • 1970-01-01
      相关资源
      最近更新 更多