为什么在显式的getter-only接口实现上使用私有setter是违法的?

Abe*_*bel 54 c# inheritance interface explicit-interface

我倾向于支持显式接口实现而非隐式接口实现,因为我认为针对接口而不是针对实现进行编程通常是可取的,而且在处理Web服务时通常是必需的.

也就是说,我想知道为什么以下是非法的显式接口声明和合法的隐式接口:

interface IConnection
{
    string ConnectionString { get; }
}

class Connection1 : IConnection
{
    // private set is illegal, won't compile
    string IConnection.ConnectionString { get; private set; }
}

class Connection2 : IConnection
{
    // private set is legal now, it is not part of the interface
    string ConnectionString { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

我知道如何解决这个问题,因为同时拥有一个显式和隐式接口是合法的,而且我可以使隐式接口实现完全私有.

然而,我想知道这背后的原因.因为从技术上讲,内部编译的私有方法set_IConnection_ConnectionString不需要是接口的一部分,对吧?它可以被视为辅助setter,而不是接口的一部分,因为它处于隐式实现情况中.

更新:作为奖励,看似令人困惑,在我看来不太正确的编译错误,您收到的是以下内容:

访问者的可访问性修饰符必须比属性Connection1.ConnectionString更具限制性

请问,更严格的private,怎么......什么?

Dam*_*ver 64

调用显式接口成员的唯一方法是将对象强制转换为正确的接口,然后在该接口上调用该成员.但是一旦你投了IConnection,IConnection.ConnectionString就没有了.

所以没有办法调用这个私有的setter方法.

  • (反思之外) (11认同)
  • @Abel如果你经常尝试访问具体类型的显式实现的接口成员,这样做很烦人,这是一个非常强烈的迹象,你应该隐式实现成员,而不是明确地实现它们.我认为在这个例子中不需要显式实现. (7认同)

sup*_*cat 10

问题是当显式声明接口成员时,编译器会生成一个private具有"不可发音"名称的实现,并且不提供代码(即使在实现类中)引用该实现的方法.

基本上,当一个人说void IFoo.Moo(),一个人说不希望Moo在类范围内定义一个名字; 因此,编译器不会.为了private set工作,该成员必须是一个"可发音"的名称,并且该成员被明确实现的事实被视为一个人不希望该名称的指示Moo.

在实践中,这里的补救措施可能与许多其他情况相同,在这种情况下,必须有一个名称可以发音的接口实现,但不会在其名称下公开公开:声明一个接口实现,除了链接到其他成员之外什么都不做具有适当的可访问性,例如,如果派生类不应该能够影响值的值:

private readonly int _foo = whatever;
public int IFOO.Foo { get {return _foo;}}
Run Code Online (Sandbox Code Playgroud)

或者,如果派生类应该能够影响它,或者

protected int _foo = whatever;
public int IFOO.Foo { get {return _foo;}}
Run Code Online (Sandbox Code Playgroud)

要么

private int _foo = whatever;
protected virtual int setFoo(int value) { _foo = value; }
protected virtual int getFoo() { return _foo; }
public int IFOO.Foo { get {return getFoo();}}
Run Code Online (Sandbox Code Playgroud)

在vb.net中,接口可以使用受保护的类成员实现,但C#不提供此类工具.


Mag*_*gus 7

我认为问题的核心是界面只有它所需要的东西.如果它不公开,它自然不是界面的一部分.因此,当您显式实现接口时,它不存在.

在隐式的情况下,您的代码适合接口,但不完全受其约束.如果需要,您可以添加更多内容.

获取有关原因的信息需要语言设计师来回答您.但是,对我来说似乎合乎逻辑:如果它不是接口的一部分,则无法在接口中实现/访问它.