我正在追踪一个错误,我在Avalon Dock 2.0源代码中找到了这个:
public abstract class LayoutContent : LayoutElement, /* ... */, ILayoutPreviousContainer
{
// ...
[XmlIgnore]
string ILayoutPreviousContainer.PreviousContainerId
{
get;
set;
}
protected string PreviousContainerId
{
get { return ((ILayoutPreviousContainer)this).PreviousContainerId; }
set { ((ILayoutPreviousContainer)this).PreviousContainerId = value; }
}
}
ILayoutPreviousContainer
有一名成员string PreviousContainerId { get; set; }
。
这种模式有什么作用?我知道除非您先将PreviousContainerId
转换为LayoutContent
,否则无法从继承子树外获取/设置ILayoutPreviousContainer
。但我不明白为什么你会想要这个。
在研究这种模式后,我发现这个SO post让我更加困惑。通过这种方式实现它,它看似类似于只有一个virtual
属性,它将以一种错综复杂的方式实现:
public class SpecificLayoutContent : LayoutContent, ILayoutPreviousContainer
{
// override LayoutContent.PreviousContainerId since it casts 'this' to an ILayoutPreviousContainer
// which will then call this property
string ILayoutPreviousContainer.PreviousContainerId{ /* ... */ }
}
我错过了什么吗?
答案 0 :(得分:2)
protected
属性无法隐式或显式地实现接口属性。因此,如果您希望从此类和派生类轻松直接访问,则需要一个protected
属性和另一个"隐藏"显式实现接口的属性。
查看您的示例,可以考虑切换两个属性的角色,例如protected
一个是自动属性,而实现一个的接口是指自动属性(而不是另一个)方式)。
你看到了什么选择?如果是public
(因此隐式实现),可以坚持使用单个属性,但在这种情况下,属性会暴露得更多,这显然是不希望的。
答案 1 :(得分:1)
ILayoutPreviousContainer
似乎是internal
接口。因此,就SpecificLayoutControl
的外部用户而言,接口不存在,并且在类上只定义了PreviousContainerId
属性。
通常的规则适用于protected
还是public
。我不会对此进行扩展,因为这似乎不是你的问题所在。
该班的作者已决定该属性应为protected
。但是,如果它是protected
,则它无法实现接口的属性,虽然外部用户看不到该接口,但在其他地方内部需要该接口。所以,他们就是这样实现的,其中一个属性只是转发给另一个属性。