Pregunta

¿Cómo se puede dar un C# Auto-Propiedad de un valor predeterminado?Yo tampoco uso el constructor, o volver a la antigua sintaxis.

Utilizando el Constructor:

class Person 
{
    public Person()
    {
        Name = "Default Name";
    }
    public string Name { get; set; }
}

El uso normal de la propiedad sintaxis (con un valor predeterminado)

private string name = "Default Name";
public string Name 
{
    get 
    {
        return name;
    }
    set
    {
        name = value;
    }
}

Hay una manera mejor?

¿Fue útil?

Solución

En C# 5 y versiones anteriores, para dar automático implementado propiedades de un valor predeterminado, se tienen que hacer en un constructor.

La habilidad para tener un auto propiedad de inicializadores se incluye desde C# 6.0.La sintaxis es:

public int X { get; set; } = x; // C# 6 or higher

Otros consejos

Editado en 1/2/15

C# 6 :

Con C# 6 puede inicializar auto-propiedades directamente (¡por fin!), ahora hay otras respuestas en el hilo que describir.

C# 5 y por debajo de:

A pesar de la intención de uso del atributo no es establecer, de hecho, los valores de las propiedades, puede utilizar la reflexión para siempre el conjunto de todos modos...

public class DefaultValuesTest
{    
    public DefaultValuesTest()
    {               
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
        {
            DefaultValueAttribute myAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];

            if (myAttribute != null)
            {
                property.SetValue(this, myAttribute.Value);
            }
        }
    }

    public void DoTest()
    {
        var db = DefaultValueBool;
        var ds = DefaultValueString;
        var di = DefaultValueInt;
    }


    [System.ComponentModel.DefaultValue(true)]
    public bool DefaultValueBool { get; set; }

    [System.ComponentModel.DefaultValue("Good")]
    public string DefaultValueString { get; set; }

    [System.ComponentModel.DefaultValue(27)]
    public int DefaultValueInt { get; set; }
}

Cuando en línea un valor inicial de una variable se hará de forma implícita en el constructor de todos modos.

Yo diría que esta sintaxis era la mejor práctica en C# hasta las 5:

class Person 
{
    public Person()
    {
        //do anything before variable assignment

        //assign initial values
        Name = "Default Name";

        //do anything after variable assignment
    }
    public string Name { get; set; }
}

Ya que esto le da el control de la orden de los valores asignados.

Como de C#6 hay una nueva forma:

public string Name { get; set; } = "Default Name"

DefaultValueAttribute SÓLO trabajo en el vs diseñador.No va a inicializar la propiedad de ese valor.

Ver DefaultValue atributo no está funcionando con mi Auto de la Propiedad

A veces puedo usar esto, si yo no quiero que sea realidad y persistió en mi db:

class Person
{
    private string _name; 
    public string Name 
    { 
        get 
        {
            return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
        } 

        set { _name = value; } 
    }
}

Obviamente, si no es una cadena, entonces yo podría hacer que el objeto que acepta valores null ( doble?, int?) y comprobar si es null, se devuelven un valor predeterminado, o devolver el valor que se establece para.

A continuación, te puedo hacer una verificación en mi repositorio para ver si es mi defecto y no persistir, o hacer una puerta de entrada a ver el verdadero estado de la copia de valor, antes de guardar.

Espero que ayude!

En C# 6.0 esta es una brisa!

Usted puede hacerlo en la Class propia declaración, en la declaración de propiedad de las declaraciones.

public class Coordinate
{ 
    public int X { get; set; } = 34; // get or set auto-property with initializer

    public int Y { get; } = 89;      // read-only auto-property with initializer

    public int Z { get; }            // read-only auto-property with no initializer
                                     // so it has to be initialized from constructor    

    public Coordinate()              // .ctor()
    {
        Z = 42;
    }
}

Empezando con C# 6.0, Podemos asignar valor por defecto para las propiedades implementadas automáticamente.

public string Name { get; set; } = "Some Name";

También podemos crear de sólo lectura automática de la propiedad implementado como:

public string Name { get; } = "Some Name";

Ver: C# 6:Primeras reacciones , Inicializadores para automáticamente las propiedades implementadas Por Jon Skeet

En la Versión de C# (6.0) & mayor, puedes hacer :

Para Readonly propiedades

public int ReadOnlyProp => 2;

Por tanto Modificables & Legible propiedades

public string PropTest { get; set; } = "test";

En la Versión actual de C# (7.0), puedes hacer :(El fragmento más bien se muestra cómo se puede utilizar la expresión de cuerpo get/set descriptores de acceso a hacer es más compacto cuando se utiliza con los campos de respaldo)

private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }

Además de que la respuesta ya está aceptado, para el escenario cuando se desea definir un valor predeterminado de la propiedad como la función de otras propiedades que se pueden utilizar la expresión corporal de la notación en C#6.0 (o superior) para obtener aún más elegante y concisa construcciones como:

public class Person{

    public string FullName  => $"{First} {Last}"; // expression body notation

    public string First { get; set; } = "First";
    public string Last { get; set; } = "Last";
}

Usted puede usar la anterior de la siguiente manera

    var p = new Person();

    p.FullName; // First Last

    p.First = "Jon";
    p.Last = "Snow";

    p.FullName; // Jon Snow

Con el fin de ser capaz de utilizar los de arriba "=>" notación, la propiedad debe ser de sólo lectura, y no se utiliza el descriptor de acceso get palabra clave.

Detalles sobre MSDN

poco completa de la muestra:

using System.ComponentModel;

private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
    get { return bShowGroup; }
    set { bShowGroup = value; }
}

Mi solución es el uso de un atributo personalizado que proporciona valor predeterminado de la propiedad de inicialización por la constante o el uso de la propiedad tipo de inicializador.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InstanceAttribute : Attribute
{
    public bool IsConstructorCall { get; private set; }
    public object[] Values { get; private set; }
    public InstanceAttribute() : this(true) { }
    public InstanceAttribute(object value) : this(false, value) { }
    public InstanceAttribute(bool isConstructorCall, params object[] values)
    {
        IsConstructorCall = isConstructorCall;
        Values = values ?? new object[0];
    }
}

El uso de este atributo es necesario heredar de una clase especial de la clase base-inicializador o utilizar un método auxiliar estática:

public abstract class DefaultValueInitializer
{
    protected DefaultValueInitializer()
    {
        InitializeDefaultValues(this);
    }

    public static void InitializeDefaultValues(object obj)
    {
        var props = from prop in obj.GetType().GetProperties()
                    let attrs = prop.GetCustomAttributes(typeof(InstanceAttribute), false)
                    where attrs.Any()
                    select new { Property = prop, Attr = ((InstanceAttribute)attrs.First()) };
        foreach (var pair in props)
        {
            object value = !pair.Attr.IsConstructorCall && pair.Attr.Values.Length > 0
                            ? pair.Attr.Values[0]
                            : Activator.CreateInstance(pair.Property.PropertyType, pair.Attr.Values);
            pair.Property.SetValue(obj, value, null);
        }
    }
}

Ejemplo de uso:

public class Simple : DefaultValueInitializer
{
    [Instance("StringValue")]
    public string StringValue { get; set; }
    [Instance]
    public List<string> Items { get; set; }
    [Instance(true, 3,4)]
    public Point Point { get; set; }
}

public static void Main(string[] args)
{
    var obj = new Simple
        {
            Items = {"Item1"}
        };
    Console.WriteLine(obj.Items[0]);
    Console.WriteLine(obj.Point);
    Console.WriteLine(obj.StringValue);
}

Salida:

Item1
(X=3,Y=4)
StringValue

En C# 6 y por encima de usted puede simplemente utilizar la sintaxis:

public object Foo { get; set; } = bar;

Tenga en cuenta que para tener un readonly propiedad simplemente omitir el conjunto, así como:

public object Foo { get; } = bar;

También puede asignar readonly auto-propiedades desde el constructor.

Antes de esto he respondido de la siguiente manera.

Me gustaría evitar la adición de un defecto al constructor;dejar que la dinámica de las asignaciones y evitar tener dos puntos en los que se asigna a la variable (es decir,el tipo de defecto y en el constructor).Normalmente yo simplemente le escribe una normal de la propiedad en tales casos.

Otra opción es hacer lo que ASP.Net ¿y definir valores predeterminados a través de un atributo:

http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx

En el constructor.El constructor tiene el propósito de inicializan los datos de los miembros.

Has probado a utilizar el DefaultValueAttribute o ShouldSerialize y métodos de restauración en conjunto con el constructor?Me siento como uno de estos dos métodos es necesario si usted está haciendo una clase que puedan aparecer en la superficie de diseño o en una cuadrícula de propiedades.

public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}
private string name;
public string Name 
{
    get 
    {
        if(name == null)
        {
            name = "Default Name";
        }
        return name;
    }
    set
    {
        name = value;
    }
}

Personalmente, no veo el punto de hacer de ella una propiedad en todo si no vas a hacer nada más allá de la auto-propiedad.Acaba de salir de un campo.La encapsulación de beneficio para estos elemento son sólo los arenques rojos, porque no hay nada detrás de ellos para encapsular.Si alguna vez necesita cambiar la implementación subyacente todavía estás libre para refactorizar como propiedades, sin romper ningún código dependiente.

Hmm...tal vez este será el tema de su propia pregunta más tarde

Para aclarar, sí, es necesario establecer los valores predeterminados en el constructor de la clase derivada de los objetos.Usted tendrá que asegurarse de que el constructor existe con el buen modificador de acceso para la construcción donde se utilizan.Si el objeto no está instanciado, por ejemplo,no tiene constructor (por ejemplo,métodos estáticos), entonces el valor por defecto puede ser configurado por el campo.El razonamiento aquí es que el objeto en sí se crea sólo una vez y no crear instancias de ella.

@Darren Kopp - buena respuesta, limpio y correcto.Y reitero, usted PUEDE escribir los constructores de los métodos Abstractos.Usted sólo necesita tener acceso a ellas desde la clase base al escribir el constructor:

Constructor en la Clase Base:

public BaseClassAbstract()
{
    this.PropertyName = "Default Name";
}

Constructor en Derivados / de Hormigón / Sub-Clase:

public SubClass() : base() { }

El punto aquí es que la variable de instancia extraídas de la clase base puede enterrar a su base de nombre de campo.La configuración de la actual instancia de objeto de valor de uso "de este." le permitirá correctamente de la forma de su objeto con respecto a la instancia actual y requiere niveles de permisos (modificadores de acceso) donde es crear instancias de ella.

Utilice el constructor, porque "Cuando el constructor está terminado, la Construcción debe ser terminado".las propiedades son como miembros de sus clases de espera, si usted tenía para inicializar un estado predeterminado, puede hacer que en su constructor.

Usted simplemente puede poner como este

    public sealed  class Employee
{
    public int Id { get; set; } = 101;
}
class Person 
{    
    /// Gets/sets a value indicating whether auto 
    /// save of review layer is enabled or not
    [System.ComponentModel.DefaultValue(true)] 
    public bool AutoSaveReviewLayer { get; set; }
}

Creo que esto sería hacerlo para ya givng SomeFlag el valor predeterminado es false.

private bool _SomeFlagSet = false;
public bool SomeFlag
{
    get
    {
        if (!_SomeFlagSet)
            SomeFlag = false;        

        return SomeFlag;
    }
    set
    {
        if (!_SomeFlagSet)
            _SomeFlagSet = true;

        SomeFlag = value;        
    }
}

inicializar en línea, el uso de constructores para inicializar es una mala práctica y dará lugar a más cambios importantes más adelante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top