代码之家  ›  专栏  ›  技术社区  ›  Alpha

封装动作<T>和功能<T>?

  •  11
  • Alpha  · 技术社区  · 14 年前

    我正在尝试设计一种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 base中的一个孩子,但我真的不喜欢这样。 如果我可以将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();
    
    4 回复  |  直到 14 年前
        1
  •  9
  •   Tomas Petricek    14 年前

    如果您想要一个轻量级的解决方案,那么最简单的选择就是编写两个具体的类。一个将包含类型为的属性 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; 
      }
    }
    

    如果你不想 行动 属性读/写,然后可以将操作委托作为参数传递给构造函数,并使属性为只读。

    C#需要两个不同的委托来表示函数和操作,这一事实非常烦人。人们使用的一种解决方法是定义类型 Unit 表示“无返回值”并使用它来代替 void . 那你的类型就是 函数<T> 你可以利用 Func<Unit> 而不是 行动 . 这个 单位 类型可能如下:

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

    创建 功能单元; 价值,你会写:

    Func<Unit> f = () => { /* ... */ return Unit.Value; }
    
        2
  •  2
  •   cordialgerm    14 年前

    下面的接口应该能做到这一点——它实际上是复制了可为空的模式

    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() { //... }
    }
    
        3
  •  0
  •   annakata    14 年前

    你知道你可以忽略一个方法的返回值对吧?你没有 使用它。

        4
  •  0
  •   Dean Chalk    14 年前

    简单点怎么样:

    public class ActionExecuter
    {
        private MulticastDelegate del;
        public ActionExecuter(MulticastDelegate del)
        {
            this.del = del;
        }
    
        public object Execute(params object[] p)
        {
            return del.DynamicInvoke(p);
        }
    }
    
    推荐文章