Pergunta

Como você dar um C# Auto-Propriedade de um valor padrão?Eu utilizar o construtor, ou reverter para o antigo sintaxe.

Usando o Construtor:

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

Usando normal sintaxe de propriedade (com um valor padrão)

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

Existe uma maneira melhor?

Foi útil?

Solução

No C# 5 e anteriores, para dar auto implementado propriedades de um valor padrão, você tem que fazê-lo em um construtor.

A capacidade de auto de propriedade inicializadores é incluída, uma vez que C# 6.0.A sintaxe é:

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

Outras dicas

Editado em 1/2/15

C# 6 :

Com C# 6 você pode inicializar auto-propriedades diretamente (finalmente!), agora há outras respostas no segmento que descrevem.

C# 5 e abaixo:

Embora a intenção de utilização do atributo é, na verdade, não definir os valores das propriedades, você pode usar a reflexão para sempre defini-los de qualquer maneira...

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

Quando você embutido um valor inicial para uma variável que vai ser feito implicitamente o construtor de qualquer maneira.

Eu diria que essa sintaxe foi a melhor prática em C# 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; }
}

Como este dá-lhe clara controle da ordem, são atribuídos valores.

Como de C#6 de uma nova maneira:

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

DefaultValueAttribute SÓ funcionam no vs designer.Ele não irá inicializar a propriedade a esse valor.

Ver Valor padrão do atributo não é trabalhar com a minha Auto Propriedade

Às vezes eu uso isso, se eu não quiser que ele seja, de fato, definir e persiste no meu db:

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

        set { _name = value; } 
    }
}

Obviamente, se não é uma seqüência de caracteres, em seguida, eu poderia fazer o objeto nulo ( duas vezes?, int?) e verifique se é nulo, o retorno a um padrão, ou devolver o valor é definido para.

Então eu posso fazer um cheque em meu repositório para ver se é o meu padrão e não persistem, ou se efectuar uma backdoor verificar para ver a verdadeira posição do suporte de valor, antes de salvar.

Espero que ajude!

Em C# 6.0 esta é uma brisa!

Você pode fazê-lo no Class a declaração em si, na declaração de propriedade declarações.

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

Começando com C# 6.0, Podemos atribuir o valor padrão para propriedades de auto-implementada.

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

Podemos também criar somente leitura automática implementada propriedade, como:

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

Veja: C# 6:As primeiras reações , Inicializadores para automaticamente implementada propriedades - Por Jon Skeet

Na Versão de C# (6.0) & maior, você pode fazer :

Para propriedades só de Leitura

public int ReadOnlyProp => 2;

Para tanto Gravável & Legível propriedades

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

Na Versão atual do C# (7.0), você pode fazer :(O trecho, ao invés de mostra como você pode usar a expressão de corpo get/set acessores para fazer é mais compacto quando usando, com o apoio campos)

private string label = "Default Value";

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

Além de que a resposta já aceito, para o cenário quando você deseja definir um padrão de propriedade como um função de outras propriedades que você pode usar expressão corporal notação em C#6.0 (e posterior) para ainda mais elegante e concisa construções como:

public class Person{

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

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

Você pode usar as opções acima na seguinte forma

    var p = new Person();

    p.FullName; // First Last

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

    p.FullName; // Jon Snow

A fim de ser capaz de usar o acima "=>" notação, a propriedade deve ser somente leitura e você não usar o acessador get palavra-chave.

Detalhes MSDN

pequeno exemplo completo:

using System.ComponentModel;

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

A minha solução é usar um atributo personalizado que fornece o valor padrão da propriedade de inicialização pela constante ou usando a propriedade inicializador de tipo.

[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 é necessário para herdar uma classe especial classe base-inicializador ou utilize um estático método auxiliar:

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

Exemplo de utilização:

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

Saída:

Item1
(X=3,Y=4)
StringValue

Em C# 6 e acima, você pode simplesmente usar a sintaxe:

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

Note que para ter um readonly propriedade simplesmente omitir o conjunto, assim:

public object Foo { get; } = bar;

Você também pode atribuir readonly auto-propriedades do construtor.

Antes disso eu responderam como abaixo.

Eu gostaria de evitar a adição de um padrão para o construtor;deixe que para uma dinâmica de atribuições e evitar ter dois pontos nos quais a variável é atribuída (por exemplo,o tipo de padrão e no construtor).Normalmente, eu simplesmente escrever uma propriedade normais em tais casos.

Uma outra opção é fazer o que ASP.Net não e definir padrões através de um atributo:

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

No construtor.O construtor propósito é inicializado dados de membros.

Você já tentou utilizar o DefaultValueAttribute ou ShouldSerialize e métodos de reinicialização em conjunto com o construtor?Sinto-me como um desses dois métodos é necessário se você estiver fazendo uma classe que pode mostrar-se sobre a superfície de designer ou em uma grelha de propriedade.

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

Pessoalmente, eu não vejo o ponto de torná-lo uma propriedade em tudo, se você não vai fazer nada além da auto-propriedade.Apenas deixe-a como um campo.O encapsulamento benefício para esses item são apenas pistas falsas, porque não há nada por trás deles para encapsular.Se você precisar alterar a implementação subjacente você ainda está livre para refatorar-las como propriedades sem quebrar qualquer código dependente.

Hmm...talvez este seja o sujeito de sua própria questão mais tarde

Para esclarecer, sim, você precisa definir valores padrão no construtor para a classe derivada de objetos.Você vai precisar para assegurar que o construtor existe com o próprio modificador de acesso para a construção onde é usado.Se o objeto não instanciado, e.g.ele não tem nenhum construtor (e.g.métodos estáticos), em seguida, o valor padrão pode ser definido o campo.O raciocínio aqui é que o próprio objeto será criado somente uma vez e não instanciá-lo.

@Darren Kopp - resposta boa, limpa e correta.E para reiterar, você PODE escrever construtores para métodos Abstratos.Você só precisa acessá-los a partir da classe base, ao escrever o construtor:

Construtor na Classe Base:

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

Construtor a Derivada de / Concreto / Sub-Classe:

public SubClass() : base() { }

O ponto aqui é que a variável de instância elaborado a partir da classe base pode enterrar sua base nome do campo.A configuração atual do objeto instanciado valor usando "isso." permitirá a você corretamente o formulário de seu objeto, com respeito a instância atual e necessária níveis de permissão (modificadores de acesso) onde você está instanciando-lo.

Use o construtor, porque "Quando o construtor estiver concluída, a Construção deve ser concluída".propriedades são, como os estados, classes de espera, se você tinha para inicializar um estado padrão, que em seu construtor.

Você pode put simples 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; }
}

Eu acho que isso faria isso por ya givng SomeFlag um padrão de false.

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

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

        SomeFlag = value;        
    }
}

inicializar em linha, usando construtores para inicializar é uma prática ruim e vai levar mais significativas alterações posteriores.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top