una propiedades property multiples interfaz interfaces inicializar implementar implement con como atributos c# inheritance interface explicit-interface

c# - propiedades - ¿Por qué es ilegal tener un setter privado en una implementación de interfaz explícitamente getter-only?



interfaz con propiedades c# (5)

Tiendo a favorecer las implementaciones de interfaces explícitas sobre las implícitas, ya que creo que la programación contra la interfaz en lugar de una implementación es generalmente preferible, además cuando se trata de servicios web a menudo es una necesidad.

Dicho esto, me preguntaba por qué lo siguiente es ilegal con una declaración de interfaz explícita y legal con una implícita:

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; } }

Sé cómo solucionar esto, ya que es legal tener una interfaz explícita e implícita, además de que puedo hacer que la implementación de la interfaz implícita sea completamente privada.

Sin embargo, me pregunto sobre el razonamiento detrás de esto. Porque técnicamente, el método privado compilado internamente set_IConnection_ConnectionString no necesita ser parte de la interfaz, ¿verdad? Simplemente podría verse como un setter auxiliar, no como parte de la interfaz, ya que está en la situación de implementación implícita.

Actualización: como extra, el error de compilación aparentemente confuso y, en mi opinión, no del todo correcto que recibe es el siguiente:

El modificador de accesibilidad del acceso debe ser más restrictivo que la propiedad Connection1.ConnectionString

Disculpe, más restrictivo que private , ¿cómo ... qué?


Creo que el núcleo del problema es que la interfaz solo tiene lo que necesita. Si no es público, naturalmente no es parte de la interfaz. Cuando implementa explícitamente la interfaz, no existe, por lo tanto, existe.

En el caso implícito, su código se ajusta a la interfaz, pero no está totalmente restringido. Puede agregar más cosas si es necesario.

Obtener información sobre por qué esto requiere un diseñador del idioma para responderle. Sin embargo, me parece lógico: si no es parte de la interfaz, no puede implementarlo / acceder a él como parte de la interfaz.


El problema es que cuando un miembro de la interfaz se declara explícitamente, el compilador genera una implementación private con un nombre "impronunciable" y no proporciona ningún medio por el cual el código, incluso dentro de la clase implementadora, haga referencia a esa implementación.

Básicamente, cuando uno dice void IFoo.Moo() , uno está diciendo que uno no desea definir un nombre Moo dentro del alcance de la clase; en consecuencia, el compilador no lo hará. Para que funcione el private set , el miembro debe ser un nombre "pronunciable", y el hecho de que el miembro se implementó explícitamente se toma como una indicación de que uno no quiere que el nombre sea Moo .

En la práctica, el remedio aquí es probablemente el mismo que para muchos otros casos donde es necesario tener una implementación de interfaz cuyo nombre sea pronunciable, pero que no esté públicamente expuesto bajo su nombre: declarar una implementación de interfaz que no hace más que encadenar a otros miembros que tienen la accesibilidad adecuada, por ejemplo, si las clases derivadas no pueden afectar el valor del valor:

private readonly int _foo = whatever; public int IFOO.Foo { get {return _foo;}}

o, si las clases derivadas deberían poder afectarlo,

protected int _foo = whatever; public int IFOO.Foo { get {return _foo;}}

o

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();}}

En vb.net, las interfaces pueden implementarse usando miembros de clase protegidos, pero C # no ofrece dicha facilidad.


La única forma de invocar a un miembro de interfaz explícito es lanzar el objeto a la interfaz correcta y luego invocar al miembro en esa interfaz. Pero una vez que has lanzado a IConnection , IConnection.ConnectionString no tiene setter.

Así que no hay forma de invocar este método privado setter.


La declaración de propiedad es una cosa atómica que contiene un getter y un setter. Debe coincidir con la interfaz.

Si permites esto, entonces aparentemente el captador y el colocador son vistos como cosas diferentes. En ese caso, no sirve de nada limitarlo a las partes privadas. En ese caso, la interfaz solo dicta que tiene que haber una propiedad que pueda leerse, y usted también puede hacerlo de manera grabable.

De todos modos, aparentemente es una decisión de diseño para hacerlo atómico.


Quizás la implementación explícita de la interfaz no se debe ver como parte de la clase en sí, sino como un tipo de adaptador de su interfaz a la clase. Dada esta vista; considere la siguiente implementación:

public interface I { string S { get; set; } } class C : I { public C() { this.S = "Hello World"; //compile error: explicit implementation not accessible } string I.S { get; set; } }

En la clase C, la propiedad S ni siquiera es accesible de forma privada porque es una implementación explícita. ¿No sería un mal diseño, en primer lugar, tener una implementación concreta de un campo no accesible por la implementación en sí?

Además, en su ejemplo, nunca sería accesible crear un setter para la implementación explícita; ya que la propiedad solo es accesible cuando se IConnection a la interfaz IConnection . Ahí solo tiene un getter.