2011-12-20 12 views
19

Si cambio el modificador de acceso del colocador de una propiedad pública de privado a público, ¿causa esto algún cambio de rotura en los otros ensamblajes que lo refieren?¿Es un cambio radical el que modifica el modificador de acceso de una propiedad pública?

+0

No, esos otros ensambles nunca antes pudieron usar la propiedad. –

+0

@Hans, el comprador de la propiedad es público, por lo que otras asambleas pueden usarlo. – mkus

+0

Bueno, no estás cambiando el captador ¿verdad? El compilador JIT no tiene ningún problema con la declaración de propiedad modificada. –

Respuesta

31

ACTUALIZACIÓN: This question was the topic of my blog in January 2012. Gracias por la gran pregunta!


que suponer que por "cambio importante" que quiere decir "cuando vuelva a compilar código que dependía de esta asamblea, no código que utiliza para compilar compilar todavía?"

Según esa definición, estrictamente hablando, sí, hacer público un establecimiento de propiedad que solía ser privado es un cambio radical. Suponga que tiene este código:

// Assembly Alpha 
public class Charlie 
{ 
    public int P { get; private set; } 
} 
public class Delta 
{ 
    public int P { get; set; } 
} 

Y luego, en otro montaje que hace referencia a Alfa:

// Assembly Echo 
class Foxtrot 
{ 
    static void M(Action<Charlie> f) {} 
    static void M(Action<Delta> f) {} 
    static void Golf() 
    { 
     M(y=>{y.P = 123;}); 
    } 
} 

Compilar montaje Echo. La clase Foxtrot tiene un método Golf que sobrecarga la resolución en M. M tiene dos sobrecargas; uno que toma una acción sobre Charlie y otro que toma una acción en Delta. Si el parámetro lambda y es de tipo Charlie, entonces el cuerpo lambda produce un error de accesibilidad y, por lo tanto, esa sobrecarga de M no es un candidato aplicable. La resolución de sobrecarga elige la segunda sobrecarga y la compilación tiene éxito.

Ahora cambia el conjunto Alpha para que el setter de Charlie.P sea público. Usted recompila Echo. Ahora obtiene un error de resolución de sobrecarga porque ambas sobrecargas de M son igualmente válidas y ninguna es mejor que la otra. La compilación de Echo falla debido al cambio en Alpha. Tu cambio a Alpha fue un cambio radical.

La pregunta no es "¿es esto un cambio radical?" Claramente es; casi todos los cambios son algún tipo de cambio radical. La pregunta debería ser si el cambio de rotura realmente romperá a alguien en la práctica, y si es así, ¿cuál es el costo de arreglar el descanso en comparación con el beneficio de la nueva característica?

+2

¿Qué le pasó a Bravo? – kvb

+20

@kvb: Una vez tuve que llamar por teléfono a una aerolínea para cambiar una reserva y la servicial señora del teléfono me dijo "y aquí está su número de confirmación si hay un problema: 153ADN6, eso es 1-5-3-Alpha-Dog-November- 6 ", y dije" Gracias, pero ¿Delta no es la palabra de código de radio internacional para D? " y ella dijo "* ¡No decimos eso en esta aerolínea! *" Te digo que conseguir una * persona * por teléfono en una aerolínea es bastante difícil; obtener una inteligente y divertida que sabe el alfabeto de radio internacional para arrancar es una rareza de hecho. –

+2

Sería aún más gracioso si fuera en realidad Delta al que llamabas. –

5

Esto depende de cuán estricto sea el "cambio de ruptura".

Una definición es: ¿rompe la compilación o la ejecución del código de referencia.

Otro es, puede el otro código determinar que usted hizo el cambio.

Según la primera definición, este no es un cambio de rotura. Según la segunda definición, es un cambio radical.

+1

[La respuesta de Eric] (http://stackoverflow.com/a/8581029) y [Jeffrey's Answer] (http://stackoverflow.com/a/8581019) ofrecen casos extremos en los que se romperá la compilación. – Brian

0

No lo creo, pero usted debe saber cuál es la sabiduría detrás de hacer este setter privado. modificadores de acceso son importantes para los consumidores de la biblioteca y en la encapsulación.

3

Podría ser, si esos otros conjuntos usan reflexión para probar la presencia del colocador.

Pero el código de enlace anticipado no se romperá.

Otra cosa a considerar es si esto es un cambio en la semántica. Si la propiedad se estableció anteriormente solo durante la construcción, y ahora se puede modificar en cualquier momento, eso definitivamente podría perjudicar a los consumidores que almacenaron el valor en caché, lo usaron como una clave de diccionario, etc.

2

Dado que la visibilidad de la propiedad se incrementa ahora no debería haber ningún problema con los ensamblados enlazados estáticamente y las referencias estáticas, esos ensamblajes solo trataban su propiedad como de solo lectura hasta ahora y continúan haciéndolo.

El único problema que podría surgir aquí es si algunos ensambles utilizan la reflexión para obtener información sobre sus propiedades y realizar algunas acciones.

Por ejemplo, si se trata de una propiedad de un objeto de negocio y utiliza vinculantes para mostrar sus datos en algún control, como GridView o ListView (independiente del marco actual) de datos, podría ser que este la propiedad será reconocida como "actualizable" ahora y el usuario puede cambiar algunos valores que usted (y algunos otros ensambles) considera inmutables hasta el momento.

17

Es un cambio radical, ya que puede provocar que el código existente ya no compile.

Algunos idiomas no le permiten anular una propiedad sin anular todos los accesors visibles. VB es ese lenguaje.

Digamos que tiene la siguiente clase C#:

namespace TestLibrary 
    public class A { 
     public virtual int X { 
      get { return 0; } 
      private set { Console.WriteLine("A.set_X called."); } 
     } 
    } 
} 

En un proyecto de VB que hace referencia a su biblioteca, que tiene una definición de clase:

Class B : Inherits TestLibrary.A 
    Public Overrides ReadOnly Property X As Integer 
     Get 
      Return MyBase.X 
     End Get 
    End Property 
End Class 

Aviso modificador ReadOnly en la propiedad. Esto es necesario en VB, porque solo está definiendo el captador.Si lo deja fuera, se obtiene un error de tiempo de compilación:

Property without a 'ReadOnly' or 'WriteOnly' specifier must provide both a 'Get' and a 'Set'.

Ahora, quitar el modificador private del colocador en su clase de C#:

namespace TestLibrary 
    public class A { 
     public virtual int X { 
      get { return 0; } 
      set { Console.WriteLine("A.set_X called."); } 
     } 
    } 
} 

Ahora obtendrá un tiempo de compilación error en el código VB:

'Public Overrides ReadOnly Property X As Integer' cannot override 'Public Overridable Property X As Integer' because they differ by 'ReadOnly' or 'WriteOnly'.

el mismo código que hace referencia a su biblioteca no se compila después de realizar el cambio, por lo que es un cambio importante.

+5

¡Bueno! Los saltos entre idiomas son algunos de los más complicados. –

+0

Realmente odio cómo se implementan las propiedades en.red; Lo que realmente tiene la ventaja de tener tres tipos de propiedades, una de las cuales incluye dos métodos, en lugar de simplemente tener propiedades getters y setters, son métodos con algún atributo que indica que, para propósitos de sintaxis, depuración, serialización, etc. debe considerarse como propiedades? Si fuera posible para una rutina aceptar un parámetro de tipo 'Propiedad ', podría ver un beneficio real tener el getter y el setter unidos como una sola entidad, pero no lo es. Entonces, ¿cuál es el beneficio? – supercat

+0

@supercat Así es exactamente como funcionan las propiedades en .NET: IL nunca llama propiedades, solo métodos. Las propiedades existen solo en metadatos. El hecho de que los métodos getter y setter no sean de fácil acceso es una cuestión de diseño del lenguaje: son métodos públicos pero están ocultos por la mayoría de los lenguajes porque tienen el atributo 'SpecialName'. Por qué C# explícitamente le impide llamar a estos métodos, no lo sé. –

Cuestiones relacionadas