我正在尝试为某种IExecutable接口进行设计。我不会详细介绍,但重点是我有几个需要从基类执行的动作。它们可能采用不同的参数(没什么大不了的),它们可能/可能不会返回值。
到目前为止,这是我的设计:
public abstract class ActionBase
{
// ... snip ...
}
public abstract class ActionWithResultBase<T>: ActionBase
{
public abstract T Execute();
}
public abstract class ActionWithoutResultBase: ActionBase
{
public abstract void Execute();
}
到目前为止,我的每个具体动作都需要来自ActionWithResultBase或ActionWithoutResult基础的孩子,但我真的不喜欢这样。 如果我可以将Execute的定义移动到ActionBase,考虑到具体类可能会或可能不会返回值,我将实现我的目标。
有人告诉我这可以通过使用Func和Action来完成,我完全同意,但我找不到一种方法将它放到一个单独的类中,以便调用者知道该操作是否将返回一个值或不。
简介:我想做的事情如下:
// Action1.Execute() returns something.
var a = new Action1();
var result = a.Execute();
// Action2.Execute() returns nothing.
var b = new Action2();
b.Execute();
如果你想要一个轻量级的解决方案,那么最简单的选择就是编写两个具体的类。一个将包含类型的属性 Action
另一种属性 Func<T>
:
public class ActionWithResult<T> : ActionBase {
public Func<T> Action { get; set; }
}
public class ActionWithoutResult : ActionBase {
public Action Action { get; set; }
}
然后你可以像这样构造两种类型:
var a1 = new ActionWithResult<int> {
CanExecute = true,
Action = () => {
Console.WriteLine("hello!");
return 10;
}
}
如果你不想做 Action
属性读/写,然后您可以将操作委托作为参数传递给构造函数,并使属性只读。
C#需要两个不同的委托来表示函数和动作这一事实非常烦人。人们使用的一种解决方法是定义类型 Unit
代表“没有回报价值”并用它代替 void
。然后你的类型就是 Func<T>
你可以使用 Func<Unit>
代替 Action
。该 Unit
类型可能如下所示:
public class Unit {
public static Unit Value { get { return null; } }
}
创建一个 Func<Unit>
价值,你会写:
Func<Unit> f = () => { /* ... */ return Unit.Value; }
以下接口应该可以解决这个问题 - 它本质上是复制Nullable模式
public interface IActionBase
{
bool HasResult { get; }
void Execute() { }
object Result { get; }
}
public interface IActionBase<T> : IActionBase
{
new T Result { get; }
}
public sealed class ActionWithReturnValue<T> : IActionBase<T>
{
public ActionWithReturnValue(Func<T> action) { _action = action; }
private Func<T> _action;
public bool HasResult { get; private set; }
object IActionBase.Result { get { return this.Result; } }
public T Result { get; private set; }
public void Execute()
{
HasResult = false;
Result = default(T);
try
{
Result = _action();
HasResult = true;
}
catch
{
HasResult = false;
Result = default(T);
}
}
}
public sealed class ActionWithoutReturnValue : IActionBase
{
public bool HasResult { get { return false; } }
object IActionBase.Result { get { return null; } }
public void Execute() { //... }
}
你知道你可以忽略方法的返回值吗?你没有 有 使用它。
简单的事情:
public class ActionExecuter
{
private MulticastDelegate del;
public ActionExecuter(MulticastDelegate del)
{
this.del = del;
}
public object Execute(params object[] p)
{
return del.DynamicInvoke(p);
}
}