使用成员隐藏(`new`)来获得更具体的返回类型

时间:2010-07-08 08:46:05

标签: c# inheritance member-hiding

我正在考虑使用new重新定义子类中的成员,以使更具体的返回类型可用。问题是:这是一个好主意,还是要求麻烦?

要解决的问题是当存在多个“镜像”类层次结构时,其中来自每个层次结构层的类型引用到另一个层次结构的相同级别。这很难解释,所以这里有一个例子:

class A1 {}
class A2 : A1 {}
class A3 : A2 {}

abstract class B1
{
  protected A1 myA;

  A1 MyA { get { return myA; } }
}

abstract class B2 : B1
{
  new A2 MyA { get { return (A2)myA; } }
}

class B3 : B2
{
  new A3 MyA 
  { 
    get { return (A3)myA; } 
    set { myA = value; }
  }
}

有代码只处理抽象“级别”1(A1 / B1等),同样适用于其他所有级别。当每个“级别”看到类型尽可能具体时,这将是很好的。目前,我在最顶层定义了类型,并在调用代码中始终向下转换。有时我使用另一个名称为某个“级别”添加另一个成员,这会导致更多冗余成员。我想让它更清洁。

(泛型不是一个选项,因为B2如果不知道B3就不会有用(它需要额外的接口)。如果有很多类型(例如还有C1 / 2/3,D1 / 2/3 ...)会有太多的泛型参数。从技术上讲它会起作用,但它会变得非常复杂。)

此外,我将序列化其中一些类(DataContractSerializer),其中一些将使用NHibernate映射到数据库。

有没有人做过这样的事情?值得推荐吗?有没有其他方法可以解决同样的问题?

编辑:由于讨论了关于强制转换和属性的实现,我稍微改变了代码。这实际上不是问题。我只是尝试编写尽可能少的代码来做一个简短的例子。

2 个答案:

答案 0 :(得分:2)

我认为你正在向后做...堕落者会失败,你应该用向上的方式设计它。 IEnumerable的实施是这种模式最常见的例子。

最派生的类型需要负责创建派生最多的结果,然后可以重写基类型中的虚方法,以通过upcast返回最大的派生结果(可能是隐式的)。

答案 1 :(得分:2)

我会这样做。

这只是为了保存打字而且会降低您的效果,因为B3.MyA基本上会return (A3)(A2)this.MyA;。只有在必要时才能直接b3.MyA as A3进行太多不必要的演员表。

此外,如果您忘记MyA B3 A3A1类型的对象,您的演员表将失败,因为它将是A2类型的对象或Technically it would work, but it just gets very complicated.或其他什么。你可以很容易地在腿上射击。

编辑:我所写的内容是:这是一种类型安全的方法,永远不会。您可以最大限度地降低这样做的风险(例如您编辑的代码显示),但仍有可能。恕我直言,这种结构的好处并不能证明这种危险是正确的。

Edit2 :请注意通用方法中的public abstract class B1<TA, TC> where TA: A1 where TC: A1 { public TA MyA { get; protected set; } public TC MyC { get; protected set; } } public abstract class B2<TA, TC> : B1<TA, TC> where TA : A2 where TC : A2 { } public class B3 : B2<A3, A3> { }

没那么复杂恕我直言。为了比较:

using

更少的代码,更好的安全性,请记住,如果您不喜欢打字过多,可以随时使用using ClassicB2 = MemberHiding.B2<MemberHiding.A3, MemberHiding.A3>; ClassicB2 b3 = new B3(); 语句:

{{1}}