microsoft - property c# get set
Diferencia entre propiedad y campo en C#3.0+ (10)
El primero:
public string MyString {get; set; }
es una propiedad; el segundo ( public string MyString
) denota un campo.
La diferencia es que ciertas técnicas (enlace de datos ASP.NET para instancias) solo funcionan en propiedades y no en campos. Lo mismo ocurre con la serialización XML: solo las propiedades se serializan, los campos no se serializan.
Me doy cuenta de que parece ser un duplicado de ¿Cuál es la diferencia entre un campo y una propiedad en C #? pero mi pregunta tiene una ligera diferencia (desde mi punto de vista):
Una vez que lo sé
- No usaré mi clase con "técnicas que solo funcionan en propiedades" y
- No usaré el código de validación en getter / setter.
¿Hay alguna diferencia (excepto el estilo / desarrollo futuro), como algún tipo de control al establecer la propiedad?
¿Hay alguna diferencia adicional entre:
public string MyString { get; set; }
y
public string myString;
(Soy consciente de que la primera versión requiere C # 3.0 o superior y que el compilador crea los campos privados).
Encapsulación
En la segunda instancia que acaba de definir una variable, en el primero, 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, aparecen de manera diferente en Intellisense :)
Editar: Actualización para la pregunta actualizada de OP. Si desea ignorar las otras sugerencias aquí, la otra razón es que simplemente no es un buen diseño de OO. Y si no tiene una muy buena razón para hacerlo, siempre elija una propiedad sobre una variable / campo público.
Entre otras respuestas y ejemplos, creo que este ejemplo es útil en algunas situaciones.
Por ejemplo, supongamos que tiene una property
OnChange
como la siguiente:
public Action OnChange { get; set; }
Si desea utilizar delegados de lo que necesita para cambiarlo, OnChange
a un field
como este:
public event Action OnChange = delegate {};
En tal situación protegemos nuestro campo del acceso no deseado o la modificación.
Hay otra diferencia importante entre campos y propiedades.
Al usar WPF, solo puede enlazar a propiedades públicas. La vinculación a un campo público no funcionará. Esto es cierto incluso cuando no se implementa INotifyPropertyChanged
(aunque siempre debería hacerlo).
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).
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 otros han mencionado. 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.
Los campos y las 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.
Aquí hay una lista de diferencias:
- Los campos se pueden usar como entrada para
out/ref
argumentos deout/ref
. Las propiedades no pueden. - Un campo siempre arrojará el mismo resultado cuando se lo llame varias veces (si omitimos problemas con múltiples hilos). 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 para ejecutarse. Los campos no tienen efectos secundarios y siempre serán tan rápidos como se pueda esperar para un tipo determinado.
- Las propiedades admiten accesibilidad diferente para getters / setters: los campos no (pero los campos se pueden hacer de forma
readonly
) - Al utilizar la reflexión, las propiedades y los campos se tratan como diferentes
MemberTypes
por lo que se ubican de manera diferente (GetFields
vsGetProperties
por ejemplo) - El compilador JIT puede tratar el acceso a la propiedad de manera 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í.
Los usuarios son más que campos. Otros ya han señalado varias diferencias importantes, y voy a agregar una más.
Las propiedades toman parte 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 un estado no válido como a la persona que realiza la llamada al anular la salida de la propiedad no asignada.
Pero podríamos impulsar el diseño aún más. Por ejemplo, la interfaz puede no tratar con el colocador. Es bastante legítimo decir que los consumidores de la interfaz IPerson
solo están interesados en obtener la propiedad, no en establecerla:
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
La implementación previa de la clase Person
satisface 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 implementación concreta se toma en consideración, por ejemplo, por 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 acerca de los emisores de propiedades; no le compete a él conocerlo. El consumidor solo necesita getters, y obtiene getters de la interfaz, es decir, del contrato.
Otra implementación completamente válida de IPerson
sería una clase de persona inmutable y una fábrica de persona correspondiente:
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, el consumidor una vez más no tiene conocimiento de llenar las propiedades. 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.
Siempre debe usar propiedades en lugar de campos para cualquier campo público. Esto asegura que su biblioteca tenga 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 las bibliotecas existentes, entonces todas las los módulos dependientes que usan su biblioteca también necesitan ser reconstruidos.
Un par de diferencias rápidas y obvias
Una propiedad puede tener palabras clave accesorias.
public string MyString { get; private set; }
Una propiedad puede ser anulada en descendientes.
public virtual string MyString { get; protected set; }