una - valores por defecto c#




¿Cómo le das a una propiedad automática de C#un valor predeterminado? (15)

En C # 6.0 esto es una brisa!

Puede hacerlo en la declaración de Class sí misma, en las declaraciones de declaración de propiedad.

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;
    }
}

¿Cómo le das a una propiedad automática de C # un valor predeterminado? Utilizo el constructor o vuelvo a la sintaxis anterior.

Usando el Constructor:

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

Usando sintaxis de propiedad normal (con un valor predeterminado)

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

¿Hay alguna manera mejor?



Además de la respuesta ya aceptada, para el escenario cuando desea definir una propiedad predeterminada en función de otras propiedades, puede usar la notación del cuerpo de la expresión en C # 6.0 (y superior) para construcciones aún más elegantes y concisas como:

public class Person{

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

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

Puedes usar lo anterior de la siguiente manera.

    var p = new Person();

    p.FullName; // First Last

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

    p.FullName; // Jon Snow

Para poder utilizar la notación "=>" anterior, la propiedad debe ser de solo lectura y no debe usar la palabra clave obtener acceso.

Detalles en MSDN


Creo que esto lo haría por ti, dándole a SomeFlag un valor predeterminado de falso.

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

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

        SomeFlag = value;        
    }
}


Editar 1/2/15

Con C # 6 puede inicializar propiedades automáticas directamente (¡por fin!), Ahora hay otras respuestas en el hilo que describen eso.

Para C # 5 y abajo:

Aunque el uso previsto del atributo no es realmente establecer los valores de las propiedades, puede usar la reflexión para establecerlos siempre 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; }
}

En C # 6 y más arriba puedes simplemente usar la sintaxis:

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

Tenga en cuenta que para tener una propiedad de solo readonly simplemente omita el conjunto, así:

public object Foo { get; } = bar;

También puede asignar propiedades automáticas de readonly desde el constructor.

Antes de esto respondí como abajo.

Evitaría agregar un valor predeterminado al constructor; deje eso para asignaciones dinámicas y evite tener dos puntos en los que se asigna la variable (es decir, el tipo predeterminado y en el constructor). Por lo general, simplemente escribiría una propiedad normal en tales casos.

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

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


En el constructor. El propósito del constructor es inicializar sus miembros de datos.


Inicializar en línea, usar constructores para inicializar es una mala práctica y llevará a más cambios de ruptura más adelante.


Mi solución es usar un atributo personalizado que proporcione la inicialización de propiedades de valor predeterminado por constante o utilizando el inicializador de tipo de propiedad.

[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];
    }
}

Para usar este atributo es necesario heredar una clase del inicializador de clase base especial o usar un método auxiliar estático:

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

Personalmente, no veo el punto de convertirlo en una propiedad si no vas a hacer nada más allá de la propiedad automática. Solo déjalo como un campo. El beneficio de encapsulación para estos elementos son solo pistas falsas, porque no hay nada detrás de ellos para encapsular. Si alguna vez necesita cambiar la implementación subyacente, todavía puede refactorizarlos como propiedades sin romper ningún código dependiente.

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


Use el constructor porque "Cuando el constructor haya terminado, la construcción debería estar terminada". las propiedades son como los estados que tienen sus clases; si tuviera que inicializar un estado predeterminado, lo haría en su constructor.



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; }
}

public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}




automatic-properties