2008-10-06 13 views
12

Con el nuevo enfoque de tener el get/set dentro del attribut de la clase de esa manera:C# 3.0 Propiedades automáticas, ¿por qué no acceder al campo directamente?

public string FirstName { 
     get; set; 
    } 

Por qué simplemente no sólo lleva el atributo FirstName pública sin descriptor de acceso?

+0

posible duplicado de [getters y setters implementados automáticamente frente a campos públicos] (http://stackoverflow.com/questions/111461/auto-implemented-getters-and-setters-vs-public-fields) – nawfal

Respuesta

30

Dos de los grandes problemas con acceso directo a la variable dentro de la clase (campo/atributo) son:

1) No puede fácilmente databind contra los campos.

2) Si expone campos públicos de sus clases no se puede cambiar posteriormente las propiedades (por ejemplo: para añadir lógica de validación a los emisores)

+1

(Re 2) ¿Los campos y las propiedades no tienen la misma sintaxis al acceder a ellos? –

+2

@damagednoob: el IL generado por el compilador es diferente y el código de reflexión es diferente porque las propiedades y los campos son diferentes. Es por eso que se considera un cambio radical. Si puede recompilar todos los códigos del cliente usted mismo, y no usa el reflejo, podría funcionar para usted. –

+1

Creo que el punto 2 es extremadamente menor, a menos que esté escribiendo algo así como el framework .NET. No es común cambiar una biblioteca y esperar insertar la biblioteca actualizada sin que la aplicación recompile a los clientes, y si se trata de un tipo interno (la mayoría de los tipos en primer lugar), el argumento es un completo no iniciador en el primer lugar. –

14

Porque, en el futuro, si cambia la implementación, el código que utiliza la interfaz actual no se romperá.

Por ejemplo, implementa una clase simple con un campo público y comienza a usar su clase en algunos módulos externos. Un mes después descubre que necesita implementar la carga diferida en esa clase. Entonces necesitarías transformar el campo en una propiedad. Desde el punto de vista del módulo externo de ciew, puede parecer el mismo sintaxis, pero no lo es. Una propiedad es un conjunto de funciones, mientras que un campo es un desplazamiento en una instancia de clase.

Al usar una propiedad, efectivamente se reduce el riesgo de que la interfaz cambie.

3

Esto sobre todo se reduce a ella habiéndose convertido en una codificación común convención. Hace que sea fácil agregar código de procesamiento personalizado si lo desea. Pero tienes razón, técnicamente no hay una necesidad real de esto. Sin embargo, si agrega procesamiento personalizado más adelante, esto le ayudará a no romper la interfaz.

0

creo que la pregunta está preguntando por qué no hacer lo siguiente ...

public string FirstName { } 

Por qué molestarse con los descriptores de acceso cuando se puede acortarlo a lo anterior. Creo que la respuesta es que al requerir los accesores, resulta obvio para la persona que lee el código que se trata de un conjunto estándar. Sin ellos, puede ver arriba, es difícil detectar que esto se está implementando automáticamente.

+0

Esto proporciona un error de "propiedad o indexador debe tener al menos un descriptor de acceso". – BlackWasp

+0

también lo hace obvio para el compilador {get; } o {set; } o {get; conjunto interno; } etc ... El acceso faltante significa que no hay acceso. –

1

La clave es que el compilador traduce la propiedad "under the hood" en un par de funciones, y cuando tiene un código que parece que está usando la propiedad, en realidad está llamando funciones cuando se compila en IL.

Digamos que crea esto como un campo y tiene el código en un ensamblaje separado que usa este campo. Si más adelante cambia la implementación y decide convertirla en propiedad para ocultar los cambios del resto de su código, aún necesita volver a compilar y volver a implementar el otro ensamblado. Si es una propiedad desde el principio, las cosas simplemente funcionarán.

0

Para el 99% de los casos, exponer un campo público está bien.

El consejo común es usar campos: "Si expone campos públicos de sus clases, no puede cambiarlos posteriormente a propiedades". Yo sé que todos queremos que nuestro código sea a prueba de futuro, pero hay algunos problemas con este pensamiento:

  • Los consumidores de la clase, probablemente, puede volver a compilar cuando cambia su interfaz.

  • El 99% de sus miembros de datos nunca tendrá que convertirse en propiedades no triviales. Es speculative generality. Estás escribiendo un montón de código que probablemente nunca será útil.

  • Si necesita compatibilidad binaria entre versiones, hacer que los miembros de datos en las propiedades probablemente no sean suficientes. Como mínimo, solo debe exponer la interfaz y ocultar todos los constructores, y exponer las fábricas (consulte el código a continuación).


public class MyClass : IMyClass 
{ 
    public static IMyClass New(...) 
    { 
     return new MyClass(...); 
    } 
} 

Es un problema difícil, tratando de hacer que el código que va a trabajar en un futuro incierto. Realmente difícil.

Does anyone have an example of a time when using trivial properties saved their bacon?

+0

Hmm, ¿alguien puede adivinar por qué mi código no formatea como código? –

+0

Sí, es difícil hacer un código a prueba de futuro. Por lo tanto, debe tomar todas las precauciones que pueda, por ejemplo, usar propiedades en lugar de campos públicos. Es tan simple que es realmente obvio. –

+0

@Jay Bazuzi: Parece que el formato de código no funciona en WMD si se encuentra en el medio de una lista con viñetas. Si agrega algo entre la lista y el código, se formateará correctamente.Acabo de agregar una regla horizontal por falta de algo útil para poner en el medio. –

0

Cuando se obtiene un error y necesita saber qué métodos están modificando sus campos y cuando, que le importe mucho más. Colocar accesos de propiedad de peso liviano por adelantado ahorra una cantidad fenomenal de dolor en caso de que surja un error relacionado con el campo que envuelve. He estado en esa situación un par de veces y no es agradable, especialmente cuando se trata de estar relacionado con la reincorporación.

Hacer este trabajo por adelantado y pegar un punto de interrupción en un accesorio es mucho más fácil que las alternativas.

-1

Conserva la encapsulación del objeto y reduce el código para que sea más fácil de leer.

2

Este estilo de notación es más útil cuando se mezcla la accesibilidad para el captador y el colocador. Por ejemplo, puede escribir:

public int Foo { get; private set; } 

También puede poner un colocador interna, o incluso hacer que el comprador privado y lo público colocador.

Esta notación evita la necesidad de escribir explícitamente una variable privada solo para manejar el problema clásico del valor internamente editable/legible externamente.

Cuestiones relacionadas