为什么在一个显式的只有getter的接口实现上拥有一个private setter是非法的?
我倾向于支持显式接口实现而不是隐式接口实现,因为我认为对接口进行编程而不是针对实现进行编程通常是可取的,而且在处理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; } }
我知道如何解决这个问题,因为具有显式和隐式接口是合法的,而且我可以使隐式接口实现完全私有化。
但是我想知道这背后的原因。 因为在技术上,内部编译的私有方法set_IConnection_ConnectionString
不需要成为接口的一部分,对吧? 它可以被看作是辅助设置者,而不是接口的一部分,因为它处于隐含的实现状态。
更新:作为奖金,看似混乱,在我看来不是很正确的编译错误,你收到的是以下内容:
访问器的辅助function修饰符必须比属性Connection1.ConnectionString更具限制性
对不起,比private
更有限制 ,怎么样?
调用显式接口成员的唯一方法是将该对象转换为正确的接口,然后调用该接口上的成员。 但是,一旦你投到IConnection
, IConnection.ConnectionString
没有setter。
所以没有办法调用这个私有的setter方法。
问题是,当明确声明接口成员时,编译器会生成一个具有“不可发音”名称的private
实现,并且不提供哪个代码(即使在实现类中)来引用该实现。
基本上,当一个人说void IFoo.Moo()
,人们不希望在类范围内定义一个名字Moo
; 因此,编译器不会。 为了private set
工作,会员必须是一个“发音”的名字,并明确实施该成员的事实被视为一个不希望名称为Moo
的迹象。
在实践中,这里的补救措施可能与其他许多情况下的补救措施是一样的,在这种情况下,必须有一个接口实现,其名称是可发音的,但是不能以其名称公开披露:声明一个接口实现,该接口实现除了链接到其他成员它具有适当的可访问性,例如,如果派生类不应该能够影响值:
private readonly int _foo = whatever; public int IFOO.Foo { get {return _foo;}}
或者,如果派生类应该能够影响它,要么
protected int _foo = whatever; public int IFOO.Foo { get {return _foo;}}
要么
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();}}
在vb.net中,接口可以使用受保护的类成员来实现,但C#不提供这样的function。
我认为问题的核心是接口只有它所需要的。 如果它不公开,它自然不是界面的一部分。 因此,当你显式地实现接口时,它不存在。
在隐含的情况下,你的代码适合界面,但不完全受其约束。 如果需要,您可以添加更多的东西。
获取信息为什么这将需要一个语言的devise师来回答你。 但是,对我来说这似乎是合乎逻辑的: 如果它不是接口的一部分,则不能实现/访问它作为接口的一部分。
属性声明是一个包含getter和setter的primefaces事物。 它应该匹配界面。
如果你愿意的话,那么显然吸气剂和二手烟被认为是不同的东西。 在这种情况下,将其限制为私有也没有用处。 在这种情况下,接口只是规定必须有一个可以读取的属性,而且你也可以自由写入。
无论如何,显然这是一个devise决定,使其primefaces。
也许显式的接口实现不应该被看作是类本身的一部分,而是作为从接口到类的一种适配器。 有了这个观点, 考虑下面的实现:
public interface I { string S { get; set; } } class C : I { public C() { this.S = "Hello World"; //compile error: explicit implementation not accessible } string IS { get; set; } }
在C类中,属性S甚至不是私人可访问的,因为它是一个明确的实现。 首先要具体实现一个领域不能被实现本身访问,那么devise不是不好的吗?
而且,在你的例子中,为显式实现创build一个setter将永远不可访问; 因为该属性只有在投射到IConnection
接口时才可以访问。 在那里只有一个getter。