定义一个可以接受Action或Func委托的方法的最好方法

本文关键字:方法 Func Action 一个 定义 | 更新日期: 2023-09-27 18:06:23

我想介绍一个方法/函数,它可以接收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>这样的东西

定义一个可以接受Action或Func委托的方法的最好方法

如何通过扩展方法使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());    

一种可能的解决方案是,您可以将重复的位提取出来,以在同一类中单独的方法,因此,像这样…

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
}

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

一些非常丑陋的代码,有代码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)();
}