定义一个可以接受Action或Func委托的方法的最好方法
本文关键字:方法 Func Action 一个 定义 | 更新日期: 2023-09-27 18:06:23
我想介绍一个方法/函数,它可以接收Action
或Func<T>
,并且根据它得到的内容,它应该返回void
或T
。
现在我必须把这个方法写成两个几乎相同的版本,就像这样。
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>
这样的东西
如何通过扩展方法使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)();
}