Atributo .NET DefaultValue

Escuché que las personas dicen algunas cosas diferentes sobre el atributo DefaultValue incluye:

  • “Establece el valor de la propiedad antes de que cualquier otra persona la use”.
  • “No funciona para autopropiedades”.
  • “Es solo para decoración. Debe establecer manualmente valores predeterminados reales”.

¿Cuál (si hay alguno) es correcto? ¿ DefaultValue realmente establece los valores predeterminados? ¿Hay casos en que no funciona? ¿Es mejor simplemente no usarlo?

El lugar donde normalmente uso DefaultValue es para las clases que se serializan / deserializan a XML. No establece el valor predeterminado durante la creación de instancias y no afecta las propiedades automáticas.

Desde MSDN:

Un DefaultValueAttribute no hará que un miembro se inicialice automáticamente con el valor del atributo. Debe establecer el valor inicial en su código.

MSDN – DefaultValueAttribute Class


Editar: como señala Roland, y como otros mencionaron en sus respuestas, el atributo también lo usa el diseñador de formularios

Al igual que todos los atributos, son metadatos, y como tal “Solo es para decoración. Debe establecer manualmente valores predeterminados reales”. está más cerca.

MSDN continúa para decir sobre DefaultValueAttribute :

Un DefaultValueAttribute no hará que un miembro se inicialice automáticamente con el valor del atributo. Debe establecer el valor inicial en su código.

es decir, aún necesita hacer que el constructor coincida con lo que dice que es el valor predeterminado para que el código que confía en que todavía funcione, como la Serialización XML integrada lo use para determinar si serializar la propiedad o no; del mismo modo, el diseñador de formularios utilizará DefaultValue para resolver qué código se debe generar automáticamente.

Para actualizar esto cuatro años después: Actualmente, establecer el parámetro DefaultValueHandling de JSON.net hace que DefaultValue funcione como esperaba @aaron:

 [JsonProperty("allowUploading",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] [DefaultValue(true)] public bool AllowUploading { get; set; } 

En realidad puedes “forzarlo” a trabajar en cualquier clase con bastante facilidad.

Primero necesita escribir el método de extensión de objeto en el espacio de nombres del sistema:

 public static class ObjectExtensions { public static void InitializePropertyDefaultValues(this object obj) { PropertyInfo[] props = obj.GetType().GetProperties(); foreach (PropertyInfo prop in props) { var d = prop.GetCustomAttribute(); if (d != null) prop.SetValue(obj, d.Value); } } } 

Luego, en el constructor de una clase que es lo suficientemente alta en la jerarquía de las clases que realmente necesita dicha inicialización automática del valor predeterminado, solo necesita agregar una línea:

  public MotherOfMyClasses() { this.InitializePropertyDefaultValues(); } 

“Establece el valor de la propiedad antes de que cualquier otra persona la use”. -> No, el valor predeterminado es solo para el diseñador. un valor predeterminado no se seralizará en el código del diseñador.

“No funciona para autopropiedades”. -> No

“Es solo para decoración. Debe establecer manualmente valores predeterminados reales”. -> No. Debido a la Serialización de Diseñador. Pero debes configurarlo manualmente.

De la ayuda de MSDN :

 AttributeCollection^ attributes = TypeDescriptor::GetProperties( this )[ "MyProperty" ]->Attributes; /* Prints the default value by retrieving the DefaultValueAttribute * from the AttributeCollection. */ DefaultValueAttribute^ myAttribute = dynamic_cast(attributes[ DefaultValueAttribute::typeid ]); Console::WriteLine( "The default value is: {0}", myAttribute->Value ); 

Necesito establecer el atributo de valor predeterminado a algo no estático. ¿Cómo puedo configurarlo cuando quiero?


Se soluciona anulando las funciones de ShouldSerialize en la clase que contiene las propiedades.

Ejemplo:

 property System::String^ Z { System::String^ get(){...} void set(System::String^ value) {...} } bool ShouldSerializeZ() { return Z !=  } 

En las últimas versiones de C# , puedes hacer:

 public class InitParam { public const int MyInt_Default = 32; public const bool MyBool_Default = true; [DefaultValue(MyInt_Default)] public int MyInt{ get; set; } = MyInt_Default; [DefaultValue(MyBool_Default)] public bool MyBool{ get; set; } = MyBool_Default; } 

puedes hacer que este tipo de magia suceda con los marcos orientados a aspectos como Pensamiento tardío o Postesharp.