¿Cuál es la diferencia entre un campo y una propiedad?

Resuelto asked hace 16 años • 33 respuestas

En C#, ¿qué diferencia a un campo de una propiedad y cuándo se debe utilizar un campo en lugar de una propiedad?

 avatar Nov 17 '08 15:11
Aceptado

Las propiedades exponen campos. Los campos deben (casi siempre) mantenerse privados para una clase y acceder a ellos mediante las propiedades get y set. Las propiedades proporcionan un nivel de abstracción que le permite cambiar los campos sin afectar la forma externa en que acceden a ellos las cosas que usan su clase.

public class MyClass
{
    // this is a field.  It is private to your class and stores the actual data.
    private string _myField;

    // this is a property. When accessed it uses the underlying field,
    // but only exposes the contract, which will not be affected by the underlying field
    public string MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
        }
    }

    // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
    // used to generate a private field for you
    public int AnotherProperty { get; set; } 
}

@Kent señala que las Propiedades no están obligadas a encapsular campos, podrían realizar un cálculo en otros campos o cumplir otros propósitos.

@GSS señala que también se puede realizar otra lógica, como la validación, cuando se accede a una propiedad, otra característica útil.

Cory avatar Nov 17 '2008 08:11 Cory

Los principios de la programación orientada a objetos dicen que el funcionamiento interno de una clase debe estar oculto al mundo exterior. Si expones un campo, en esencia estás exponiendo la implementación interna de la clase. Por lo tanto, envolvemos los campos con Propiedades (o métodos en el caso de Java) para darnos la posibilidad de cambiar la implementación sin romper el código dependiendo de nosotros. Dado que podemos poner lógica en la Propiedad, también nos permite realizar lógica de validación, etc., si la necesitamos. C# 3 tiene la noción posiblemente confusa de propiedades automáticas. Esto nos permite definir simplemente la propiedad y el compilador de C#3 generará el campo privado por nosotros.

public class Person
{
   private string _name;

   public string Name
   {
      get
      {
         return _name;
      }
      set
      {
         _name = value;
      }
   }
   public int Age{get;set;} //AutoProperty generates private field for us
}
 avatar Nov 17 '2008 09:11

Una diferencia importante es que las interfaces pueden tener propiedades pero no campos. Para mí, esto subraya que las propiedades deben usarse para definir la interfaz pública de una clase, mientras que los campos deben usarse en el funcionamiento interno y privado de una clase. Como regla general, rara vez creo campos públicos y, de manera similar, rara vez creo propiedades que no sean públicas.

 avatar Nov 17 '2008 13:11

Te daré un par de ejemplos del uso de propiedades que podrían hacer girar los engranajes:

  • Inicialización diferida : si tiene la propiedad de un objeto que es costoso de cargar, pero al que no se accede mucho en ejecuciones normales del código, puede retrasar su carga a través de la propiedad. De esa manera, simplemente permanece ahí, pero la primera vez que otro módulo intenta llamar a esa propiedad, verifica si el campo subyacente es nulo; si lo es, continúa y lo carga, sin que el módulo que lo llama lo sepa. Esto puede acelerar enormemente la inicialización del objeto.
  • Seguimiento sucio: del que aprendí en mi propia pregunta aquí en StackOverflow. Cuando tengo muchos objetos cuyos valores pueden haber cambiado durante una ejecución, puedo usar la propiedad para rastrear si es necesario volver a guardarlos en la base de datos o no. Si no ha cambiado ni una sola propiedad de un objeto, el indicador IsDirty no se activará y, por lo tanto, la funcionalidad de guardado lo omitirá al decidir qué se debe volver a la base de datos.
Chris avatar Nov 17 '2008 14:11 Chris

Al utilizar Propiedades, puede generar un evento cuando se cambia el valor de la propiedad (también conocido como PropertyChangedEvent) o antes de que se cambie el valor para admitir la cancelación.

Esto no es posible con (acceso directo a) campos.

public class Person {
 private string _name;

 public event EventHandler NameChanging;     
 public event EventHandler NameChanged;

 public string Name{
  get
  {
     return _name;
  }
  set
  {
     OnNameChanging();
     _name = value;
     OnNameChanged();
  }
 }

 private void OnNameChanging(){       
     NameChanging?.Invoke(this,EventArgs.Empty);       
 }

 private void OnNameChanged(){
     NameChanged?.Invoke(this,EventArgs.Empty);
 }
}
Jehof avatar Jun 26 '2009 06:06 Jehof