封装动作< T>和Func< T&gt ;? [英] Encapsulating Action<T> and Func<T>?

查看:129
本文介绍了封装动作< T>和Func< T&gt ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为某种IExecutable接口设计.我不会详细介绍,但要点是,我有几个需要从基类执行的Action.它们可能采用不同的参数(没什么大不了的),并且它们可能会/可能不会返回值.

I'm trying to make a design for some sort of IExecutable interface. I will not get into details, but the point is that I have several Actions that need to be executed from a base class. They may take different parameters (no big deal), and they may/may not return a value.

到目前为止,这是我的设计:

So far, this is my design:

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,考虑到具体类可能会或可能不会返回值,那么我将实现我的目标.

So far, each of my concrete actions need to be a child from either ActionWithResultBase or ActionWithoutResult base, but I really don't like that. If I could move the definition of Execute to ActionBase, considering that the concrete class may or may not return a value, I will have achieved my goal.

有人告诉我,可以完全使用Func和Action来做到这一点,对此我完全同意,但是我找不到一种将其归入一个类的方法,以便调用者知道操作是否要返回是否有值.

Someone told me this could be done with using Func and Action, for which I totally agree, but I can't find a way to have that into one single class so that the caller would know if the action is going to return a value or not.

简述:我想做类似的事情:

Brief: I want to do something like:

// 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>的属性:

If you want a lightweight solution, then the easiest option would be to write two concrete classes. One will contain a property of type Action and the other a property of type Func<T>:

public class ActionWithResult<T> : ActionBase { 
  public Func<T> Action { get; set; } 
}

public class ActionWithoutResult : ActionBase {
  public Action Action { get; set; }
}

然后,您可以像这样构造两种类型:

Then you can construct the two types like this:

var a1 = new ActionWithResult<int> { 
  CanExecute = true,
  Action = () => { 
    Console.WriteLine("hello!");
    return 10; 
  }
}

如果您不想使Action属性为读/写,则可以将操作委托作为参数传递给构造函数,并使该属性为只读.

If you don't want to make Action property read/write, then you could pass the action delegate as an argument to the constructor and make the property readonly.

C#需要两个不同的代表来表示函数和动作的事实非常令人讨厌.人们使用的一种解决方法是定义一个表示无返回值"的类型Unit,并使用它代替void.然后,您的类型将仅为Func<T>,并且可以使用Func<Unit>而不是Action. Unit类型可能如下所示:

The fact that C# needs two different delegates to represent functions and actions is quite annoying. One workaround that people use is to define a type Unit that represents "no return value" and use it instead of void. Then your type would be just Func<T> and you could use Func<Unit> instead of Action. The Unit type could look like this:

public class Unit {
  public static Unit Value { get { return null; } }
}

要创建Func<Unit>值,请输入:

Func<Unit> f = () => { /* ... */ return Unit.Value; }

这篇关于封装动作&lt; T&gt;和Func&lt; T&gt ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆