Inicialização de variável de membro c #; melhor pratica?

É melhor inicializar variables ​​de membro de class na declaração

private List _things = new List(); private int _arb = 99; 

ou no construtor padrão?

 private List _things; private int _arb; public TheClass() { _things = new List(); _arb = 99; } 

É simplesmente uma questão de estilo ou há compensações de desempenho, de uma forma ou de outra?

Em termos de desempenho, não há diferença real; inicializadores de campo são implementados como lógica de construtor. A única diferença é que os inicializadores de campo acontecem antes de qualquer construtor “base” / “this”.

A abordagem de construtor pode ser usada com propriedades auto-implementadas (inicializadores de campo não podem) – ie

 [DefaultValue("")] public string Foo {get;set;} public Bar() { // ctor Foo = ""; } 

Além disso, tenho a tendência de preferir a syntax do inicializador de campo; Eu acho que mantém as coisas localizadas – ou seja

 private readonly List items = new List(); public List Items {get {return items;}} 

Eu não tenho que ir para cima e para baixo para encontrar onde é atribuído …

A exceção óbvia é onde você precisa executar lógica complexa ou lidar com parâmetros de construtor – nesse caso, a boot baseada em construtor é o caminho a percorrer. Da mesma forma, se você tiver vários construtores, seria preferível que os campos sempre fossem configurados da mesma maneira – para que você possa ter os seguintes:

 public Bar() : this("") {} public Bar(string foo) {Foo = foo;} 

edit: como um comentário lateral, note que no acima, se existem outros campos (não mostrados) com inicializadores de campo, então eles são apenas diretamente inicializados nos construtores que chamam base(...) – isto é, a public Bar(string foo) ctor. O outro construtor não executa inicializadores de campo, pois sabe que eles são feitos pelo this(...) ctor.

Na verdade, os inicializadores de campo, conforme você demonstra, são uma forma abreviada conveniente. Na verdade, o compilador copia o código de boot no início de cada construtor de instância que você define para o seu tipo.

Isso tem duas implicações: primeiro, qualquer código de boot de campo é duplicado em cada construtor e, segundo, qualquer código incluído em seus construtores para inicializar campos para valores específicos irá, na verdade, reatribuir os campos.

Portanto, com relação ao desempenho, e com relação ao tamanho do código compilado, é melhor você mover os inicializadores de campo para os construtores.

Por outro lado, o impacto sobre o desempenho e o código ‘bloat’ geralmente são insignificantes, e a syntax do inicializador de campo tem o importante benefício de diminuir o risco de você esquecer de inicializar algum campo em um de seus construtores.

Uma grande limitação com inicializadores de campo é que não há como agrupá-los em um bloco try-finally. Se uma exceção for lançada em um inicializador de campo, todos os resources que foram alocados nos inicializadores anteriores serão abandonados; não há como evitar isso. Outros erros na construção podem ser tratados, se desajeitadamente, por ter um construtor de base protegido aceitar um IDisposable por referência, e apontá-lo para si mesmo como sua primeira operação. Pode-se então evitar chamar o construtor, exceto através de methods de fábrica que, no caso de exceção, chamarão Dispose no object parcialmente criado. Essa proteção permitirá a limpeza de IDisposables criados em inicializadores de class derivada se o construtor da class principal falhar após “contrabandear” uma referência ao novo object. Infelizmente, não há como fornecer essa proteção se um inicializador de campo falhar.

Use os inicializadores de campo ou crie uma function Init (). O problema em colocar essas coisas em seu construtor é que, se você precisar adicionar um segundo construtor, acabará com o código copiar / colar (ou ignorá-lo e acabar com variables ​​não inicializadas).

Eu iria inicializar onde declarado. Ou faça o (s) construtor (es) chamar uma function Init ().

Por exemplo variables, é em grande parte uma questão de estilo (prefiro usar um construtor). Para variables ​​estáticas, há um benefício de desempenho para inicializar em linha (nem sempre possível, é claro).

É realmente com você.
Eu frequentemente inicializo-os inline, porque eu não gosto de ter um construtor quando eu realmente não preciso de um (eu gosto de classs pequenas!).

No ponto adicionado ao acima – Você sempre tem um construtor ao implementar classs que possuem uma implementação. Se você não declarar um, o instrutor padrão será inferido pelo compilador [public Foo () {}]; um construtor que não aceita argumentos.

Muitas vezes eu gosto de oferecer as duas abordagens. Permitir construtores para aqueles que desejam usá-los e permitir que os inicializadores de campo para situações em que você deseja usar uma implementação simplificada ou padrão de sua class / tipo. Isso adiciona flexibilidade ao seu código. Tenha em mente que qualquer um pode usar o inicializador de campo padrão se escolher … certifique-se de declará-lo manualmente se você oferecer mais de um construtor – public Foo () {}