Como você dá um Auto-Propriedade C # um valor padrão?

Como você dá um Auto-Propriedade C # um valor padrão? Eu uso o construtor ou reverto para a syntax antiga.

Usando o construtor:

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

Usando a syntax normal da propriedade (com um valor padrão)

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

Existe uma maneira melhor?

No C # 5 e anterior, para dar às propriedades implementadas automaticamente um valor padrão, você precisa fazê-lo em um construtor.

A capacidade de ter inicializadores de propriedade automática está incluída desde o C # 6.0. A syntax é:

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

Editar 1/2/15

Com o C # 6, você pode inicializar as propriedades automáticas diretamente (finalmente!), Agora há outras respostas no encadeamento que descrevem isso.

Para C # 5 e abaixo:

Embora o uso pretendido do atributo não seja realmente definir os valores das propriedades, você pode usar a reflection para defini-las sempre …

 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ê inline um valor inicial para uma variável, isso será feito implicitamente no construtor.

Eu diria que esta syntax era a melhor prática em C # até 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 isso lhe dá um controle claro dos valores do pedido são atribuídos.

A partir do C # 6, há um novo caminho:

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

DefaultValueAttribute SOMENTE trabalha no designer vs. Não irá inicializar a propriedade para esse valor.

Consulte o atributo DefaultValue não está funcionando com a propriedade Auto

Às vezes eu uso isso, se eu não quero que seja realmente definido e persistido no meu database:

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

Obviamente, se não é uma string, então eu poderia tornar o object anulável (double ?, int?) E verificar se é nulo, retornar um padrão ou retornar o valor para o qual ele está definido.

Então eu posso fazer uma verificação no meu repository para ver se é meu padrão e não persistir, ou fazer um check-in de backdoor para ver o verdadeiro status do valor de apoio, antes de salvar.

Espero que ajude!

Começando com C # 6.0 , podemos atribuir valor padrão para propriedades auto-implementadas.

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

Também podemos criar propriedades auto-implementadas somente leitura como:

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

Veja: C # 6: Primeiras reações, Inicializadores para propriedades automaticamente implementadas – Por Jon Skeet

No C # 6.0 isso é uma brisa!

Você pode fazer isso na declaração de Class , nas declarações de declaração de propriedade.

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

pequena amostra completa:

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

Na versão do c # (6.0) e maior , você pode fazer:

Para propriedades Readonly

 public int ReadOnlyProp => 2; 

Para propriedades graváveis ​​e legíveis

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

Na versão atual do C # (7.0) , você pode fazer: (O snippet em vez disso mostra como você pode usar accessrios get / set com expressão encorpada para fazer é mais compacto ao usar com campos de apoio)

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

Minha solução é usar um atributo personalizado que fornece boot de propriedade de valor padrão por constante ou usando o inicializador de tipo de propriedade.

 [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 esse atributo, é necessário herdar uma class do inicializador de class base especial ou usar um 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); } } } 

Exemplo de uso:

 public class Simple : DefaultValueInitializer { [Instance("StringValue")] public string StringValue { get; set; } [Instance] public List 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 

Além da resposta já aceita, para o cenário em que você deseja definir uma propriedade padrão como uma function de outras propriedades, é possível usar a notação do corpo da expressão no C # 6.0 (e superior) para construções ainda mais elegantes e 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"; } 

Você pode usar o acima da seguinte maneira

  var p = new Person(); p.FullName; // First Last p.First = "Jon"; p.Last = "Snow"; p.FullName; // Jon Snow 

Para poder usar a notação “=>” acima, a propriedade deve ser somente leitura e você não deve usar a palavra-chave get assessor.

Detalhes no MSDN

No C # 6 e acima, você pode simplesmente usar a syntax:

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

Note que para ter uma propriedade readonly simplesmente omita o conjunto, da seguinte forma:

 public object Foo { get; } = bar; 

Você também pode atribuir propriedades automáticas readonly do construtor.

Antes disso eu respondi como abaixo.

Eu evitaria adicionar um padrão ao construtor; deixe que para atribuições dinâmicas e evite ter dois pontos em que a variável é atribuída (ou seja, o tipo padrão e no construtor). Normalmente eu simplesmente escreveria uma propriedade normal em tais casos.

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

http://msdn.microsoft.com/pt-br/library/system.componentmodel.defaultvalueattribute.aspx

No construtor. O propósito do construtor é inicializar seus membros de dados.

Você já tentou usar os methods DefaultValueAttribute ou ShouldSerialize e Reset em conjunto com o construtor? Eu sinto que um desses dois methods é necessário se você está fazendo uma aula que pode aparecer na superfície do designer ou em uma grade de propriedades.

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

Pessoalmente, eu não vejo o ponto de torná-lo uma propriedade, se você não vai fazer nada além da propriedade de automóveis. Apenas deixe como um campo. O benefício de encapsulamento para esses itens é apenas o vermelho, porque não há nada por trás deles para encapsular. Se você precisar alterar a implementação subjacente, ainda estará livre para refatorá-las como propriedades sem quebrar nenhum código dependente.

Hmm … talvez isso seja o assunto de sua própria pergunta depois

Para esclarecer, sim, você precisa definir valores padrão no construtor para objects derivados da class. Você precisará garantir que o construtor exista com o modificador de access adequado para a construção, quando usado. Se o object não for instanciado, por exemplo, não possui um construtor (por exemplo, methods estáticos), o valor padrão pode ser definido pelo campo. O raciocínio aqui é que o object em si será criado apenas uma vez e você não o instancia.

@ Darren Kopp – boa resposta, limpo e correto. E para reiterar, você pode escrever construtores para methods abstratos. Você só precisa acessá-los da class base ao escrever o construtor:

Construtor na Classe Base:

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

Construtor em Derivado / Concreto / Subclass:

 public SubClass() : base() { } 

O ponto aqui é que a variável de instância desenhada da class base pode enterrar seu nome de campo de base. Definir o valor do object instanciado atual usando “this”. permitirá que você formem corretamente seu object com relação à instância atual e aos níveis de permissão necessários (modificadores de access) nos quais você está instanciando.

Use o construtor porque “Quando o construtor for concluído, a construção deverá ser concluída”. propriedades são como os estados de suas classs, se você tivesse que inicializar um estado padrão, você faria isso em seu construtor.

 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 para você 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 é má prática e levará a mais alterações mais tarde.