使用第二种实现的显式接口实现

时间:2014-06-04 20:24:43

标签: c# explicit-implementation

我正在追踪一个错误,我在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{ /* ... */ }
}

我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

protected属性无法隐式或显式地实现接口属性。因此,如果您希望从此类和派生类轻松直接访问,则需要一个protected属性和另一个"隐藏"显式实现接口的属性。

查看您的示例,可以考虑切换两个属性的角色,例如protected一个是自动属性,而实现一个的接口是指自动属性(而不是另一个)方式)。

你看到了什么选择?如果是public(因此隐式实现),可以坚持使用单个属性,但在这种情况下,属性会暴露得更多,这显然是不希望的。

答案 1 :(得分:1)

ILayoutPreviousContainer似乎是internal接口。因此,就SpecificLayoutControl的外部用户而言,接口不存在,并且在类上只定义了PreviousContainerId属性。

通常的规则适用于protected还是public。我不会对此进行扩展,因为这似乎不是你的问题所在。

该班的作者已决定该属性应为protected。但是,如果它是protected,则它无法实现接口的属性,虽然外部用户看不到该接口,但在其他地方内部需要该接口。所以,他们就是这样实现的,其中一个属性只是转发给另一个属性。