定义可以接受Action或Func委托的方法的最佳方法

时间:2016-09-09 08:25:22

标签: c#

我想介绍一个方法/函数,它可以接收ActionFunc<T>,并且根据它得到的内容,它应该返回voidT

现在我必须用两个几乎相同的版本来编写这个方法。

public void WrapAction(Action action) {
  // do something...
  action();
  // do something more...
}

public T WrapFunc(Func<T> func) {
  // do something...
  var result = func();
  // do something more...
  return result;
}

是否有任何技术可以避免这种重复?

相比之下,例如在Javascript中,我可以灵活地接受任何类型的函数(可能是void)并只返回它的结果,如果它是void,那么它将返回undefined。但是在C#中,我不能写出类似Func<void>的东西。

3 个答案:

答案 0 :(得分:1)

一种可能的解决方案是,您可以将重复位提取出来以分离同一类中的方法,如下所示......

public void WrapAction(Action action) {
  DoInitialBit();
  action();
  DoFinalBit();
}

public T WrapFunc(Func<T> func) {
  DoInitialBit();
  var result = func();
  DoFinalBit();
  return result;
}

private void DoInitialBit()
{
    // Do the thing before you call the Action or Func
}

private void DoFinalBit()
{
    // Do the thing after you call the Action or Func
}

显然,您可能需要根据需要从这些附加方法中获取输入或返回输出,但这是它的一般要点。

答案 1 :(得分:1)

如何通过扩展方法从动作中删除Func<bool>并减少包装器以仅处理Func<T>

public static class ActionExtensions
{
    public static Func<bool> ToFunc(this Action action)
    {
        return () =>
        {
            action();
            return true;
        };
    }
}

然后WrapAction可以简单地拨打WrapFunc

public void WrapAction(Action action)
{
    WrapFunc(action.ToFunc());
}

或删除WrapAction并直接使用WrapFunc

WrapFunc(action.ToFunc());    

答案 2 :(得分:1)

代码DRY的一些非常难看的代码:

static void Main(string[] args)
{
    var p = new Program();
    p.WrapAction(() => Console.WriteLine(123));
    Console.WriteLine(p.WrapFunc<string>(() => "321"));
    Console.ReadKey();
}

public void WrapAction(Action action) => WrapActionInner<object>(action);

public T WrapFunc<T>(Func<T> func) => WrapActionInner<T>(func);

private T WrapActionInner<T>(object action)
{
    if (action is Action)
    {
        ((Action)action)();
        return default(T);
    }
    return ((Func<T>)action)();
}

我们的想法是将功能包装到类型不安全的私有方法中。