【问题标题】:Looking for generic way to implement function in base class寻找在基类中实现功能的通用方法
【发布时间】:2011-04-01 01:24:09
【问题描述】:

我正在尝试在我的领域层中做一个规范模式的简单实现。

如果我有一个充满这样规范的静态类:

public static class FooSpecifications
{
  public static Func<Foo, bool> IsSuperhuman
  {
    get
    {
      return foo => foo.CanShootLasersOutOfItsEyes && foo.CanFly;
    }
  }
}

然后我可以做这样奇妙的事情:

IEnumerable<Foo> foos = GetAllMyFoos();
var superFoos = foos.Where(FooSpecifications.IsSuperhuman);

我还可以向 Foo 添加 bool 方法来确定特定实例是否符合规范:

public bool Meets(Func<Foo, bool> specification)
{
  return specification.Invoke(this);
}

鉴于 Foo 和我所有的域实体一样扩展了 DomainObject,有没有办法可以将 Meets() 的通用实现放入 DomainObject 中,以节省我在每个实体中分别实现 Meets()?

【问题讨论】:

  • 提示:您可以使用 Predicate 代替 Func
  • @Paul:可以,但是框架的最新版本,尤其是 LINQ 的趋势是使用 Func&lt;T,bool&gt; 而不是 Predicate&lt;T&gt;
  • @LukeH:有趣,不知道这个(显然)谢谢。

标签: c# functional-programming base-class generics


【解决方案1】:

这样的……

    public abstract class DomainObj<T> // T - derived type
        where T : DomainObj<T>
    {
        public bool Meets(Func<T, bool> specification)
        {
            return specification.Invoke((T) this);
        }
    }

    public class Foo : DomainObj<Foo> {}

    public class Bar : DomainObj<Bar> {}       

        Func<Foo, bool> foospec = x => true;
        Func<Bar, bool> barspec = x => true;

        var foo = new Foo();
        var bar = new Bar();
        foo.Meets(foospec);
        foo.Meets(barspec); // won't compile because of mismatched types of spec and object instance

编辑

也许将 Meet 方法翻译成扩展会更好。这将消除对类型参数的需求。

    public abstract class DomainObj
    {
    }

    public static class DomainObjExtensions
    {
        public static bool Meets<T>(this T obj, Func<T, bool> f)
            where T : DomainObj
        {
            return f(obj);
        }
    }

    public class Foo : DomainObj {}

    public class Bar : DomainObj {}

    Func<Foo, bool> foospec = x => true;
    Func<Bar, bool> barspec = x => true;

    var foo = new Foo();
    var bar = new Bar();
    foo.Meets(foospec);
    foo.Meets(barspec); // error

【讨论】:

  • 派生类声明后面的大括号是什么?当我把它们放进去时,我开始收到“命名空间不能包含成员”的编译器错误。
  • 无论哪种方式,在派生类中编译器都无法识别 DomainObject 类型,即使它们在同一个命名空间中。
  • 我的错:我粘贴了您的一些代码,但没有注意到您使用的是 DomainObj 而不是 DomainObject。
  • 这似乎可行,但现在我遇到了另一个问题。如何将派生类型转换回 DomainObject
  • 对不起,我不是说将派生类型转换为 DomainObject,而是将一个对象转换为 DomainObject。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 2021-10-17
  • 2012-01-11
  • 2014-06-01
  • 2022-08-04
  • 2010-10-27
相关资源
最近更新 更多