2009-03-17 16 views
127

me di cuenta de que parece ser un duplicado de What is the difference between a Field and a Property in C#? pero mi pregunta tiene una ligera diferencia (desde mi punto de vista):Diferencia entre la propiedad y el campo en C# 3.0 +

Una vez que sé que

  • No utilizaré mi clase con "técnicas que solo funcionan en propiedades" y
  • No utilizaré el código de validación en getter/setter.

¿Hay alguna diferencia (excepto el estilo/las de desarrollo futuro), como algún tipo de control en la configuración de la propiedad?

¿Hay alguna diferencia adicional entre:

public string MyString { get; set; } 

y

public string myString; 

(Soy consciente de que, para que la primera versión requiere C# 3.0 o superior y que el compilador no crear los campos privados .)

+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

108

Encapsulación.

En la segunda instancia que acaba de definir una variable, en la primera, hay un getter/setter alrededor de la variable. Entonces, si decides que quieres validar la variable en una fecha posterior, será mucho más fácil.

Además de que aparezcan de manera diferente en Intellisense :)

Editar: Actualización para PO pregunta actualizados - si desea ignorar las otras sugerencias aquí, la otra razón es que no es simplemente un buen diseño orientado a objetos. Y si no tiene una muy buena razón para hacerlo, siempre elija una propiedad sobre una variable/campo público.

+8

¿Por qué? ser mas facil? ¿Qué me impide convertir un campo en una propiedad y agregar un campo de respaldo privado? ¿Cómo afecta esto el código de llamada? –

+27

@Serge - Afecta al código ya compilado. Por ejemplo, si está desarrollando una biblioteca que usan varias aplicaciones, cambiar un campo a una propiedad en esa biblioteca requeriría una recompilación de cada aplicación. Si fuera una propiedad, podría actualizar la propiedad sin preocupaciones. –

+0

Estoy totalmente de acuerdo contigo, siempre uso propiedades. Solo tenía curiosidad acerca de una posible diferencia – p4bl0

7

La primera de ellas:

public string MyString {get; set; } 

es una propiedad; el segundo (public string MyString) denota un campo.

La diferencia es que ciertas técnicas (vinculación de datos ASP.NET para instancias) solo funcionan en propiedades y no en campos. Lo mismo se aplica a la serialización XML: solo las propiedades se serializan, los campos no se serializan.

+8

Incorrecto. La serialización XML SÍ serializa campos públicos. –

+2

Quizás. Pero cuando crea un Origen de datos de objeto de una clase, solo puede usar las propiedades, no los campos. (A menos que haya hecho algo mal: P) – Svish

+0

Lo bueno es DRY;) pero escribo una vez más, me gusta el fuerte papel de la propiedad en el lenguaje C#. Está mucho mejor implementado que en Java (por lo tanto, desde el principio). Muchas, quizás todas las soluciones .net solo funcionan en propiedades. WPF, ASPX y más. –

40

Un par rápidos y evidentes diferencias

  1. una propiedad puede tener palabras clave de descriptor de acceso.

    public string MyString { get; private set; } 
    
  2. Una propiedad puede ser anulada en los descendientes.

    public virtual string MyString { get; protected set; } 
    
+0

mmh .. nr 2 es interesante ... no pensé en ello – p4bl0

+1

agregar versiones a eso :) –

13

La diferencia fundamental es que un campo es una posición en la memoria donde se almacenan los datos del tipo especificado. Una propiedad representa una o dos unidades de código que se ejecutan para recuperar o establecer un valor del tipo especificado.El uso de estos métodos de acceso se oculta sintácticamente mediante el uso de un miembro que parece comportarse como un campo (en el sentido de que puede aparecer en cualquier lado de una operación de asignación).

3

Las propiedades y los campos pueden, en muchos casos, parecer similares, pero no lo son. Existen limitaciones para las propiedades que no existen para los campos, y viceversa.

Como han mencionado otros. Puede hacer que una propiedad sea de solo lectura o de solo escritura haciendo que su acceso sea privado. No puedes hacer eso con un campo. Las propiedades también pueden ser virtuales, mientras que los campos no.

Piense en las propiedades como azúcar sintáctico para las funciones getXXX()/setXXX(). Así es como se implementan detrás de escena.

145

Los campos y propiedades tienen el mismo aspecto, pero no lo son. Las propiedades son métodos y, como tales, hay ciertas cosas que no son compatibles con las propiedades y algunas cosas que pueden suceder con las propiedades, pero nunca en el caso de los campos.

He aquí una lista de las diferencias:

  • Los campos que se puede utilizar como entrada para out/ref argumentos. Las propiedades no pueden.
  • Un campo siempre arrojará el mismo resultado cuando se lo llame varias veces (si omitimos problemas con varios subprocesos). Una propiedad como DateTime.Now no siempre es igual a sí misma.
  • Las propiedades pueden arrojar excepciones: los campos nunca harán eso.
  • Las propiedades pueden tener efectos secundarios o tomar mucho tiempo en ejecutarse. Los campos no tienen efectos secundarios y siempre serán tan rápidos como se pueda esperar para un tipo determinado.
  • Propiedades apoyan diferente accesibilidad para getters/setters - campos no lo hacen (pero los campos se pueden hacer readonly)
  • Cuando se utiliza la reflexión de las propiedades y campos son tratados como diferente MemberTypes por lo que se encuentran de manera diferente (GetFields vs GetProperties por ejemplo)
  • El compilador JIT puede tratar el acceso a la propiedad de forma muy diferente en comparación con el acceso de campo. Sin embargo, puede compilarse hasta el código nativo idéntico, pero el alcance de la diferencia está ahí.
+11

Sin embargo, tenga en cuenta que varios de estos puntos no deberían ser * * * * si se emplean buenas prácticas. Es decir, las propiedades realmente nunca deberían tener efectos secundarios, ni deberían tardar mucho tiempo en ejecutarse. – Noldorin

+13

@Noldorin: Estoy de acuerdo, pero desafortunadamente * debería * es la palabra clave aquí. Con los campos ese comportamiento está garantizado. No digo que debas usar campos, pero es importante estar al tanto de las diferencias semánticas. –

+4

Sí, es suficiente. Los programadores principiantes no tienen ni idea de estas cosas a menudo, lamentablemente ... – Noldorin

10

Los accesorios son más que campos. Otros ya han señalado varias diferencias importantes, y voy a agregar una más.

Las propiedades participan en las clases de interfaz. Por ejemplo:

interface IPerson 
{ 
    string FirstName { get; set; } 
    string LastName { get; set; } 
} 

Esta interfaz se puede satisfacer de varias maneras. Por ejemplo:

class Person: IPerson 
{ 
    private string _name; 
    public string FirstName 
    { 
     get 
     { 
      return _name ?? string.Empty; 
     } 
     set 
     { 
      if (value == null) 
       throw new System.ArgumentNullException("value"); 
      _name = value; 
     } 
    } 
    ... 
} 

En esta implementación estamos protegiendo tanto a la clase Person de entrar en un estado no válido, así como la persona que llama de conseguir nula hacia fuera de la propiedad sin asignar.

Pero podríamos impulsar el diseño aún más. Por ejemplo, la interfaz puede no tratar con el colocador.Es muy legítimo decir que los consumidores de IPerson interfaz sólo están interesados ​​en conseguir la propiedad, no en su creación:

interface IPerson 
{ 
    string FirstName { get; } 
    string LastName { get; } 
} 

aplicación anterior de las satisface clase Person esta interfaz. El hecho de que le permite al llamador también establecer las propiedades no tiene sentido desde el punto de vista de los consumidores (que consumen IPerson). La funcionalidad adicional de la aplicación concreta se toma en consideración, por ejemplo, el constructor:

class PersonBuilder: IPersonBuilder 
{ 
    IPerson BuildPerson(IContext context) 
    { 

     Person person = new Person(); 

     person.FirstName = context.GetFirstName(); 
     person.LastName = context.GetLastName(); 

     return person; 

    } 
} 

... 

void Consumer(IPersonBuilder builder, IContext context) 
{ 
    IPerson person = builder.BuildPerson(context); 
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName); 
} 

En este código, el consumidor no sabe nada de los emisores de propiedad - no es su negocio saber acerca de ella. El consumidor solo necesita getters, y obtiene getters de la interfaz, es decir, del contrato.

Otra aplicación completamente válida de IPerson sería una clase de persona inmutable y una fábrica de quien corresponda:

class Person: IPerson 
{ 
    public Person(string firstName, string lastName) 
    { 

     if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName)) 
      throw new System.ArgumentException(); 

     this.FirstName = firstName; 
     this.LastName = lastName; 

    } 

    public string FirstName { get; private set; } 

    public string LastName { get; private set; } 

} 

... 

class PersonFactory: IPersonFactory 
{ 
    public IPerson CreatePerson(string firstName, string lastName) 
    { 
     return new Person(firstName, lastName); 
    } 
} 
... 
void Consumer(IPersonFactory factory) 
{ 
    IPerson person = factory.CreatePerson("John", "Doe"); 
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName); 
} 

En este ejemplo de código de consumo, una vez más no tiene conocimiento de las propiedades de relleno. El consumidor solo se ocupa de los getters y la implementación concreta (y la lógica de negocios subyacente, como probar si el nombre está vacío) se deja en manos de las clases especializadas: constructores y fábricas. Todas estas operaciones son completamente imposibles con los campos.

1

Hay otra diferencia importante entre los campos y las propiedades.

Al usar WPF, solo puede enlazar a propiedades públicas. La vinculación a un campo público será no trabajo. Esto es cierto incluso cuando no se implementa INotifyPropertyChanged (aunque siempre debería hacerlo).

+0

Bueno es SECO;) pero escribo una vez más, me gusta el papel fuerte de la propiedad en el lenguaje C#. Está mucho mejor implementado que en Java (por lo tanto, desde el principio). Muchas, quizás todas las soluciones .net solo funcionan en propiedades. WPF, ASPX y más. –

0

Siempre debe usar propiedades en lugar de campos para cualquier campo público. Esto asegura que su biblioteca tiene la capacidad de implementar la encapsulación para cualquier campo si es necesario en el futuro sin romper los códigos existentes. Si reemplaza los campos con propiedades en bibliotecas existentes entonces todos los módulos dependientes que usan su biblioteca también necesitan ser reconstruidos.

+0

"siempre" es un lema de palabra difícil. En C# (mejor que en Java) la propiedad tiene una posición fuerte, es (probablemente sin excepción) principal/método de "enlace" en ASP, WPF y otros. Pero, no obstante, puedo imaginar el diseño con el campo no ser propiedad tiene sentido (a veces) –

0

Entre otras respuestas y ejemplos, creo que este ejemplo es útil en algunas situaciones.

Por ejemplo Digamos que usted tiene un OnChangeproperty como siguiente:

public Action OnChange { get; set; } 

Si desea utilizar delegados de lo que necesita para cambiarlo OnChange a field así:

public event Action OnChange = delegate {}; 

En tal situación protegemos nuestro campo del acceso no deseado o modificación.

Cuestiones relacionadas