制作一个函数,可以采取 属性 of Action<T> 或 Action
Make a function that can take property of Action<T> or Action
我有以下两个功能:
private void CallVoidFunction(Action action, object property = null)
{
//Lots of code duplicated here
action.Invoke();
//and here between teh 2 methods
}
private void CallVoidFunction<T>(Action<T> action, object property = null)
{
//Lots of code duplicated here
action.Invoke((T)property);
//and here between teh 2 methods
}
有没有办法将这些组合成一个函数,该函数采用 Action
的通用 属性 ?
否则我会有很多重复的代码。我知道可以把重复的代码组合成函数调用,但是可以吗?
Action
和 Action<T>
似乎不是从同一个基础派生的,所以我认为它无法完成?
我正在按照它们派生的接口思路进行思考,但我看不到任何共同点?
下面是我能想到的最好的方法,但我希望有更简单的方法。
public class ActionContainer<T>
{
public ActionContainer(Action<T> actionT, Action action, object property)
{
_actionT = actionT;
_action = action;
_property = property;
}
public void Invoke()
{
if (_property != null)
_actionT.Invoke((T)_property);
else
_action.Invoke();
}
private object _property { get; set; }
private Action<T> _actionT { get; set; }
private Action _action { get; set; }
}
你应该能够像这样从第二个调用第一个,这样你就可以避免代码重复:
private void CallVoidFunction<T>(Action<T> action, object property = null)
{
CallVoidFunction(() => action.Invoke((T)property), property);
}
Action<T>
表示接受 1 个 T
类型参数的 void 函数,而 Action
表示没有参数的 void 函数。
因此您需要重载,因为没有函数与两个签名匹配。
但是,您可以使用闭包来避免重复:
private void CallVoidFunction<T>(Action<T> action, T property = default)
=> CallVoidFunction(() => action(property));
private void CallVoidFunction(Action action)
{
//...
action();
//...
}
这将接受 T
的函数包装在一个没有参数的函数中。
您还应该将 property
声明为 T
,而不是反对强制执行 type-safety。
如果 property
仅用作 action
的参数,另一种方法是完全删除通用版本并让调用者制定闭包。
如果 CallVoidFunction
确实需要以某种方式使用 property
,那么重载是您唯一的选择:
private void CallVoidFunction<T>(Action<T> action, T property = default)
{
// Do something with property..
CallVoidFunction(() => action(property));
}
这与 Johnathan Barclay 的 相似,但相反。您首先要完全实现通用版本。然后 non-generic 版本可以从通用版本派生,传递一个虚拟 (object)null
参数。
private void CallVoidFunction<T>(Action<T> action, T property = default)
{
//...
action(property);
//...
}
private void CallVoidFunction(Action action)
=> CallVoidFunction<object>(_ => action(), null);
优点是 property
在完整实现中可用,如果您出于某种原因(如日志记录)需要它。
我有以下两个功能:
private void CallVoidFunction(Action action, object property = null)
{
//Lots of code duplicated here
action.Invoke();
//and here between teh 2 methods
}
private void CallVoidFunction<T>(Action<T> action, object property = null)
{
//Lots of code duplicated here
action.Invoke((T)property);
//and here between teh 2 methods
}
有没有办法将这些组合成一个函数,该函数采用 Action
的通用 属性 ?
否则我会有很多重复的代码。我知道可以把重复的代码组合成函数调用,但是可以吗?
Action
和 Action<T>
似乎不是从同一个基础派生的,所以我认为它无法完成?
我正在按照它们派生的接口思路进行思考,但我看不到任何共同点?
下面是我能想到的最好的方法,但我希望有更简单的方法。
public class ActionContainer<T>
{
public ActionContainer(Action<T> actionT, Action action, object property)
{
_actionT = actionT;
_action = action;
_property = property;
}
public void Invoke()
{
if (_property != null)
_actionT.Invoke((T)_property);
else
_action.Invoke();
}
private object _property { get; set; }
private Action<T> _actionT { get; set; }
private Action _action { get; set; }
}
你应该能够像这样从第二个调用第一个,这样你就可以避免代码重复:
private void CallVoidFunction<T>(Action<T> action, object property = null)
{
CallVoidFunction(() => action.Invoke((T)property), property);
}
Action<T>
表示接受 1 个 T
类型参数的 void 函数,而 Action
表示没有参数的 void 函数。
因此您需要重载,因为没有函数与两个签名匹配。
但是,您可以使用闭包来避免重复:
private void CallVoidFunction<T>(Action<T> action, T property = default)
=> CallVoidFunction(() => action(property));
private void CallVoidFunction(Action action)
{
//...
action();
//...
}
这将接受 T
的函数包装在一个没有参数的函数中。
您还应该将 property
声明为 T
,而不是反对强制执行 type-safety。
如果 property
仅用作 action
的参数,另一种方法是完全删除通用版本并让调用者制定闭包。
如果 CallVoidFunction
确实需要以某种方式使用 property
,那么重载是您唯一的选择:
private void CallVoidFunction<T>(Action<T> action, T property = default)
{
// Do something with property..
CallVoidFunction(() => action(property));
}
这与 Johnathan Barclay 的 (object)null
参数。
private void CallVoidFunction<T>(Action<T> action, T property = default)
{
//...
action(property);
//...
}
private void CallVoidFunction(Action action)
=> CallVoidFunction<object>(_ => action(), null);
优点是 property
在完整实现中可用,如果您出于某种原因(如日志记录)需要它。