我经常发现自己正在处理与此相似的模式
两个继承树,其中存在某种镜像。左树中的每个子类在右树中都有一个不同的子类,即source
MappingEnd类:
public class MappingEnd
{
public NamedElement source { get; set; }
}
问题是,如何在子类中处理它。是否使用
source
关键字隐藏父new
属性?public class AssociationMappingEnd:MappingEnd
{
public new Association source { get; set; }
}
还是只提供第二个将
NamedElement
转换为Association
的属性?public class AssociationMappingEnd:MappingEnd
{
public Association associationSource
{
get
{
return (Association)this.source;
}
set
{
this.source = value;
}
}
}
我为什么要选择一个。还是有更好的方法来实现这种模式?
最佳答案
在第一种设计中,public new Association source
很容易引起麻烦。您仍然仍然可以意外地访问隐藏的成员public NamedElement source
。这不酷。
例如,看下面的伪代码:
IEnumerable<MappingEnd> MyMixedCollection = all kinds of MappingEnd objects
((AssociationMappingEnd)MyMixedCollection.First()).source //is cool
MyMixedCollection.First().source //access the hidden member, not cool
new
关键字不是最佳设计实践,因为它不会隐藏继承的成员。它所做的基本上是隐藏没有它的警告消息。我个人从不认为这是有效的设计。
第二种设计更加可靠,因为这些名称永远不会混淆
AssociationMappingEnd.associationSource is Association
AssociationMappingEnd.source is NamedElement
MappingEnd.source is NamedElement
但是,由于这些
source
和associationSource
实际上是相同的,因此可能会造成混淆。它可以工作,但是可以更好。我们不能在
override
上使用source
并给它一个新的类型,我们可以使用public virtual NamedElement source
,但是那样我们将失去类型安全。为了保持类型安全,我们可以使用泛型,如elgonzo建议的那样。左侧需要通用,因为它取决于右侧类的类型,因此我们应该从左侧的顶级类开始:
public class MappingEnd<T> where T : NamedElement
{
public T source { get; set; }
}
现在,您可以拥有以下两个类别之一或全部:
public class AssociationMappingEnd<T> : MappingEnd<T> where T : Association
{
}
public class AssociationMappingEnd : MappingEnd<Association>
{
}
现在,您只有一个带有安全类型的
source
:AssociationMappingEnd<Association>.source is Association
AssociationMappingEnd.source is Association
MappingEnd<NamedElement>.source is NamedElement
MappingEnd<Association>.source is Association
关于c# - 处理镜像继承树,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52425762/