我想介绍一个方法/函数,它可以接收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>
的东西。
答案 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)();
}
我们的想法是将功能包装到类型不安全的私有方法中。