2015-07-20 20 views
5

Ho un oggetto con List<> s esposto da proprietà. Io in genere inizializzo mie liste entro il getter proprietà come segue:Inizializzazione degli elenchi all'interno delle proprietà e nel costruttore?

public class Foo 
{ 
    private List<bar> _barList; 

    public List<bar> 
    { 
     get 
     { 
      if(_barList == null) 
      { 
       _barList = new List<Bar>() 
      } 

      return _barList; 
     } 

     set 
     { 
      _barList = value; 
     } 
    } 

    public Foo() 
    { 
    } 
} 

Tuttavia, i miei colleghi in genere preferiscono l'inizializzazione della lista nel costruttore della classe come segue:

public class Foo 
{ 
    public List<bar> BarList { get; set; } 

    public Foo() 
    { 
     BarList = new List<Bar>(); 
    } 
} 

Entrambi i casi impedire BarList da cui si accede prima è inizializzato. Il secondo sembra più pulito a causa dell'uso di autoproprietà. Tuttavia, la prima sembra un'opzione migliore, poiché l'elenco viene inizializzato solo quando viene utilizzato per la prima volta. Ci sono altre considerazioni che dovrei prendere in considerazione? C'è una buona pratica per questo?

+2

L'importante è garantire la validità dello stato della classe. Entrambi questi approcci producono lo stesso risultato esternamente, ma internamente il '_barList' pigro-inizializzato potrebbe essere nullo mentre il costruttore inizializzato' BarList' non sarà nullo quando qualcuno tenta di usarlo all'interno della classe. Bene, esternamente il risultato non è completamente lo stesso se si inizia a introdurre comportamenti multi-thread nell'equazione. –

+1

Si tratta di un approccio "caricamento ansioso" e "caricamento lento". –

+1

In questo caso, è fondamentalmente una questione di stile (e opinione, però). In C# 6.0, hai un altro modo di inizializzare una proprietà auto-implementata, come [questa risposta SO] (http://stackoverflow.com/a/40754/1389444) mostra. –

risposta

4

Se è necessario conservare la memoria, la strategia lazy è chiaramente migliore. Se l'utilizzo della memoria non è importante, la strategia entusiasta si traduce in un codice molto più semplice. È preferibile allora.

In generale è una buona cosa eliminare casi speciali. Non è una buona cosa che il campo elenco possa essere nullo per l'accesso interno.

Si noti che il codice diventa ancora più breve con C# 6 che inclina il trade-off più verso la soluzione di codice più breve.

Si noti che la versione lenta non è thread-safe per l'esecuzione concomitante del getter.

3

Oltre alla risposta di usrs, c'è un'altra risposta, usando C# 6.0, su questa domanda.

Una delle nuove funzionalità è un inizializzatore per le proprietà auto-implementate. Si potrebbe scrivere:

public class Foo 
{ 
    public List<bar> BarList { get; set; } = new List<bar>(); 
} 

Inoltre, uno sguardo ai nuovi costruttori primari, ha trovato a programmers.stackexchange article.

Questo inizializzatore verrà chiamato sull'inizializzazione dell'oggetto. In materia di consumo/prestazioni della memoria, dovrebbe essere uguale all'inizializzazione della proprietà nel costruttore.

+0

Usando questa funzione, la lista è inizializzata quando la classe è inizializzata, oppure C# gestisce l'inizializzazione "lazy" per te? Se lo fa, questo sembra di gran lunga la soluzione migliore! – Ivan

+0

L'ora di inizializzazione della classe (costruttore statico) non è possibile perché la proprietà è un membro dell'istanza, quindi deve essere l'ora di inizializzazione dell'oggetto. –

+0

Oops, intendevo dire oggetto, non classe. Quindi questa funzione sembra equivalente alla seconda opzione nell'OP .. hmm.Dal momento che nel mio caso la lista a volte non viene utilizzata, mi chiedo se il risparmio di memoria potrebbe far sì che valga la pena di scriverlo da solo. – Ivan