2010-08-20 7 views
13
private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { return _dates; } 
    set { _dates = value; } 
} 

Ouso corretto del C# proprietà

public List<Date> Dates 
{ 
    get;   
    set;  
} 

Ho sempre usato il primo, è che la pratica scorretta o un male? Non mi è mai venuto in mente che potrei semplicemente usare la seconda opzione. Mi piace avere le mie variabili incapsulate per iniziare con un carattere di sottolineatura, così posso distinguerle dai parametri del metodo. E l'ho sempre fatto in questo modo.

E 'possibile che utilizzando la prima opzione si tradurrebbe in un List<Date> oggetto in più in fase di un'istanza e poi l'intera _dates essere sostituita con value, o è più intelligente di quello?

Inoltre, che è il più importante nell'industria o è totalmente soggettivo?

+0

possibile duplicato del [C# 3.0 auto-proprietà -? Utile o no] (http://stackoverflow.com/questions/9304/c-sharp-3-0-auto- proprietà-utili-o-no) – nawfal

risposta

7

Sono equivalenti nel modulo compilato interno, ad eccezione del fatto che non è possibile accedere alla variabile privata generata dal compilatore nel secondo modulo.

Dal punto di vista dell'efficienza del codice, sono equivalenti, il compilatore just in time accede direttamente alla variabile privata senza il sovraccarico di chiamare una funzione di accesso (dopo che l'ambiente di runtime ha controllato l'accessibilità ecc.).

Dal punto di vista della codifica, preferisco la seconda versione che è più compatta (meno da scrivere, meno da leggere).

La seconda sintassi è stata introdotta in C# 3.0. Quindi la prima variante sarebbe più compatibile con i vecchi compilatori.

+0

Buone informazioni sulla compatibilità con le versioni precedenti e il codice compilato, grazie. – Nobody

7

Entrambi sono fondamentalmente uguali a causa del modo in cui .NET compila le proprietà automatiche. Le proprietà automatiche sono diventate disponibili con .NET 3.5.

+1

3.0 in realtà http://msdn.microsoft.com/en-us/library/bb384054.aspx – CaffGeek

+2

@Chad C# 3.0, ma .NET 3.5. –

+0

touche! Mi dimentico sempre che i numeri di versione non sono sincronizzati – CaffGeek

19

Utilizzare il primo se è necessario aggiungere una sorta di logica al getter/setter.

Utilizzare quest'ultimo in caso contrario. Rende le cose molto più pulite. È inoltre possibile ottenere proprietà di sola lettura utilizzando le proprietà auto:

public List<Date> Dates { get; private set; } 

Oppure, se non si vuole che la gente di aggiungere eventuali elementi all'elenco tramite la proprietà si può ricorrere alla ex sintassi:

private List<Date> _dates = new List<Date>(); 
private ReadOnlyCollection<Date> _readOnlyDates = 
    new ReadOnlyCollection<Date>(_dates); 

public ReadOnlyCollection<Date> Dates 
{ 
    get { return _readOnlyDates; } 
} 
+0

Non vorrei continuare a restituire un nuovo 'ReadOnlyCollection'. Internamente mantiene un riferimento all'elenco in modo che vengano visualizzate eventuali modifiche. – ChaosPandion

+1

Il punto è che i chiamanti non saranno in grado di modificarlo. – recursive

+0

Non chiamerei una proprietà auto con un setter privato 'read-only': può ancora essere modificato dalla classe in cui è definito, cioè non è sinonimo di parola chiave 'readonly' nei campi. –

0

Non importa. Il secondo è solo zucchero. Io uso sempre il secondo perché è più pulito, ma ogni tanto ho bisogno di accedere al valore di supporto.

0

Finché non è necessario assicurarsi che l'List<Date> sia inizializzato nel getter, si sta bene con entrambe le versioni. Ho solo suggerire che si sta utilizzando una versione e non mescolare nel codice ...

Se avete bisogno inizializzato si deve andare per la prima versione ...

private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { if (_dates == null) _dates = new List<Date>(); return _dates; } 
    set { _dates = value; } 
} 
+1

Questo è sciocco. Basta fare "Elenco privato _dates = new List ()" o inizializzare nel costruttore. Dubito che inizializzare pigro questa semplice lista comprerà qualcosa di diverso dal codice più complesso. – siride

+1

@siride - Sono d'accordo, ora se si stava inizializzando un elenco da un database che è una storia completamente diversa. – ChaosPandion

0

I credono di compilare lo stesso codice. Quest'ultimo è solo zucchero sintattico per rappresentare il primo. Tendo a pensare a quest'ultimo come un segnaposto per la logica futura che potrebbe dover essere inserito nelle proprietà, a quel punto convertirò le proprietà interessate al primo.

0

I due sono compilati all'incirca allo stesso modo (non so se il nome del campo di supporto sarebbe lo stesso, ma sarebbero funzionalmente uguali).

IIRC, la possibilità di eseguire Proprietà automatiche (public List<Date> Dates {get; set;}) è stata aggiunta in .NET 3.0 o 3.5.

4

Tendo ad utilizzare le proprietà automatiche di più perché una proprietà è un buon modo per esprimere l'intento su ciò che l'oggetto sta facendo, ma ha ancora una certa protezione.

Quasi tutti i miei dichiarazioni di proprietà assomigliano:

public bool IsBlah { get; private set; } 

Questo lo rende un piacevole, leggibile, e protetto getter.

Ma ci sono momenti in cui si desidera un campo supporto esplicito:

private bool? _isBlah; 
public bool IsBlah 
{ 
    get 
    { 
     if (_isBlah == null) 
     { 
      // Do something expensive here and set _isBlah 
      _isBlah = true; 
     } 
     return _isBlah; 
    } 
} 
1

Il primo è l'approccio originale, il secondo è un esempio della struttura più recente 'proprietà auto' per cui il compilatore genera un campo di supporto per te automaticamente

Alcune persone (me compreso) evitano di proprietà di auto perché la sintassi è facile scambiare oggetti astratti, non c'è una struttura di 'sola lettura' proprietà e la sintassi per le proprietà auto con setter privati ​​è goffo:

public List Dates 
{ 
    get; 
    private set; 
}

Inoltre, trovo scomodo avere l'implementazione interna delle mie classi che accede ai campi tramite l'API della classe.

+0

'Trovo inoltre scomodo avere l'implementazione interna delle mie classi che accede ai campi tramite l'API della classe. Esattamente! Attaccherò a quello che uso. Grazie – Nobody

1

La seconda variante è nota come auto-implemented properties ed è stata introdotta in C# 3.0 (quindi perché non è possibile averlo incontrato prima).

È preferibile utilizzare questo formato se si desidera creare proprietà semplici con backing-fields e non è necessario implementare alcuna logica in 'getter' e 'setter'. Non solo è più conciso, ma ti costringe anche ad accedere direttamente alla proprietà, piuttosto che passare attraverso il campo di supporto, che di solito è la migliore pratica.

Nota è ancora possibile inizializzare le proprietà, è sufficiente farlo tramite il costruttore.

public class MyClass 
{ 

    public List<Date> Dates 
    { 
     get;   
     set;  
    } 

    public MyClass() 
    { 
     Dates = new List<Date>(); 
    } 

} 
0

Per quanto posso ricordare, ho sempre gestito le mie proprietà di elenco dall'interno dell'oggetto, rendendole di sola lettura.

private IList<DateTime> _dates; 

public MyClass() { 
    _dates = new List<DateTime>(); 
} 

public IList<DateTime> Dates { 
    get { 
     return _dates; 
    } 
} 

In questo modo, vi assicuro che la mia lista non è mai nulla quando accedo, dal momento che il client non può assegnare.

Tuttavia, per il tuo esempio, devi solo utilizzare il precedente approccio se hai bisogno di un qualche tipo di logica quando ottieni o imposta una proprietà. Altrimenti, le proprietà automatiche fanno esattamente lo stesso, ottenendo e impostando un valore su un campo privato. Inoltre, lo { get; set; } migliora la leggibilità e aiuta altri programmatori a capire le tue intenzioni, a mio modesto punto di vista.

Per esempio:

public class MyClass { 
    private IList<DateTime> _dates; 

    public IList<DateTime> Dates { 
     get { 
      return _dates; 
     } set { 
      _dates = value; 
     } 
    } 
} 

contro

public class MyClasse { 
    public IList<DateTime> Dates { get; set; } 
} 

Il secondo modo rende più snella e più rapida, almeno per me, ciò che l'intenzione è. E diventa più veloce codificare una classe, quando non è necessaria alcuna logica all'interno di getter e setter.

In caso contrario, uno non è migliore rispetto agli altri e fa proprio la stessa cosa, parlando di ottenere e impostare semplicemente il valore della proprietà senza alcuna logica.

Ancora più importante, è necessario stare bene con il vostro codice. Se finisce, non ottieni miglioramenti, e ti piace quello che stai facendo, piuttosto che farlo. =)

+0

Puoi aggiungere il 'private set' al tuo ultimo esempio per ottenere lo stesso risultato con un codice più pulito. Ma ricordati anche di dare un riferimento a 'IList' significa che non è di sola lettura, dato che' IList' supporta 'Aggiungi',' Rimuovi', 'Cancella', ecc. Concesso, se il tuo interlocutore vuole davvero modificare la lista, lo faranno non importa cosa li passi. –

+0

@Matt Greer: Sì, davvero! Questo è generalmente quello di cui ho bisogno, ovvero permettere di aggiungere uno() o rimuovere() dall'elenco, altrimenti andrei a cercare un oggetto di livello gerarchico più alto. Oltre a ciò, la capacità di C# di definire un ambito di accesso per il getter, e un altro per il setter, lo rende molto flessibile con cui lavorare. Questa è una cosa tra le tante che mi manca lavorando con C#, visto che attualmente sto lavorando in VB.NET 2.0. –

1

Io personalmente preferisco il primo metodo in quanto consente di eseguire alcune operazioni prima del ritorno.

E.G. (Davvero un cattivo esempio)

private int _limit; 
    private int _onHand; 
    private bool returnToVendor; 

    public Item(int limit, int onHand) 
    { 
     _limit = limit; 
     _onHand = onHand; 
    } 

    public int ReturnStock 
    { 
     get 
     { 
     if(_onHand > _limit) 
     { 
      returnToVendor = true; 
      return _onHand; 
     } 
     } 

     set 
     { 
      _onHand = value; 

      if(_onHand < _limit) 
      { 
       returnToVendor = false; 
      } 
     } 
    }