2009-07-25 22 views
272

Spesso ci viene detto che dovremmo proteggere l'incapsulamento rendendo i metodi getter e setter (proprietà in C#) per i campi classe, invece di esporre i campi al mondo esterno.Campi pubblici contro Proprietà automatiche

Ma ci sono molte volte in cui un campo è solo lì per contenere un valore e non richiede alcun calcolo da ottenere o impostare. Per questi saremmo tutti fare questo numero:

public class Book 
{ 
    private string _title; 

    public string Title 
    { 
      get{ return _title; } 
      set{ _title = value; } 
    } 
} 

Beh, ho una confessione, non potevo sopportare scrivere tutto ciò che (in realtà, non è stato dover scrivere, è stato dover guardare), quindi sono diventato canaglia e ho usato campi pubblici.

poi arriva C# 3.0 e vedo hanno aggiunto le proprietà automatiche:

public class Book 
{ 
    public string Title {get; set;} 
} 

che è più ordinato, e sono grato per questo, ma in realtà, ciò che è così diverso da solo facendo un campo pubblico?

public class Book 
{ 
    public string Title; 
} 
+0

possibile duplicato di [Differenza tra proprietà e campo in C# .NET 3.5+] (http://stackoverflow.com/questions/653536/difference-between-property-and-field-in-c-sharp-net- 3-5) – nawfal

+4

Ho convertito una proprietà in una proprietà solo così ho potuto impostare un punto di interruzione sul setter –

+1

Tendo a fare qualcosa che non è una proprietà privata perché realizzando la strada che devo rifattorizzare un campo in una proprietà ha portare a qualche mal di testa inutile. [Proprietà, campi e metodi. Oh My!] (Http://www.codeducky.org/properties-fields-and-methods-oh-my/) richiama un'incompatibilità che mi ha morso in passato. –

risposta

137

In un related question ho avuto qualche tempo fa, c'era un collegamento a un post sul blog di Jeff, spiegando alcune differenze.

Properties vs. Public Variables

  • riflessione funziona in modo diverso sulle variabili vs. proprietà, quindi se ci si basa sulla riflessione, è più facile da usare tutte le proprietà.
  • Non è possibile associare dati a una variabile.
  • La modifica di una variabile in una proprietà è un cambiamento irreversibile. Per esempio:

    TryGetTitle(out book.Title); // requires a variable 
    
+17

"Cambiare una variabile in una proprietà è un cambio di rottura." Questo ovviamente si applica solo quando si scrive una libreria riutilizzabile, che la maggior parte degli sviluppatori * non * sta facendo. – Steven

+21

Inoltre, le proprietà, anche le proprietà automatiche, possono essere virtuali, dove i campi non possono. Quindi, una classe base può avere una semplice implementazione del backing field prodotta dal compilatore per un auto-prop, mentre le classi derivate possono eseguire ulteriori validazioni o altri calcoli logici. – KeithS

+22

Anche un campo è una _variabile_ e può essere passato per riferimento (parola chiave 'ref' o' out'), mentre una proprietà è una coppia di accessori e non può essere passata per riferimento. Ad esempio 'bool success = TryGetMyTitle (out myBook.Title);' che usa 'out' funzionerà con un campo e non funzionerà con una proprietà. Questo è un chiaro esempio del perché il passaggio dal campo alla proprietà è un cambiamento radicale! –

51

Il passaggio da un campo a una proprietà rompe il contratto (ad esempio, richiede tutto il codice fa riferimento a essere ricompilato). Quindi, quando hai un punto di interazione con altre classi - qualsiasi membro pubblico (e generalmente protetto), vuoi pianificare una crescita futura. Fallo usando sempre le proprietà.

Non è nulla per renderlo un auto-proprietà oggi, e 3 mesi in linea capisci che vuoi renderlo pigro-caricato, e mettere un assegno nullo nel getter. Se hai usato un campo, questo è un cambiamento di ricompilazione nel migliore dei casi e impossibile nel peggiore dei casi, a seconda di chi è il & che altro si basa sui tuoi assembly.

+1

Mi è piaciuta questa risposta perché non usa le parole "reflection", "interface" o "override". (peccato per il 'contratto') –

6

E 'tutta una questione di controllo delle versioni e la stabilità API. Non c'è alcuna differenza, nella versione 1 - ma in seguito, se si decide di rendere questa proprietà una sorta di controllo degli errori nella versione 2, non è necessario modificare la propria API - nessuna modifica del codice, da nessuna parte, diversa da la definizione della proprietà.

64

Ignorando i problemi dell'API, la cosa che ritengo più utile nell'utilizzo di una proprietà è il debug.

Il debugger CLR non supporta i punti di interruzione dei dati (la maggior parte dei debugger nativi lo fanno). Quindi non è possibile impostare un punto di interruzione sulla lettura o scrittura di un campo particolare su una classe. Questo è molto limitante in alcuni scenari di debug.

Poiché le proprietà sono implementate come metodi molto sottili, è possibile impostare punti di interruzione sulla lettura e scrittura dei loro valori. Questo dà loro una grande gamba sopra i campi.

0

Se in seguito si decide di verificare che il titolo sia univoco, confrontandolo con una raccolta o un database, è possibile farlo nella proprietà senza modificare alcun codice che dipende da esso.

Se si utilizza solo un attributo pubblico, si avrà una minore flessibilità.

La flessibilità extra senza rompere il contratto è la cosa più importante per me sull'utilizzo delle proprietà e, finché non ho effettivamente bisogno della flessibilità, l'auto-generazione ha più senso.

53

Solo perché nessuno lo ha menzionato: non è possibile definire campi su interfacce. Quindi, se devi implementare un'interfaccia specifica che definisce le proprietà, le auto-proprietà a volte sono una funzionalità davvero interessante.

+1

Direi che se hai bisogno di un'interfaccia che definisce le proprietà, dovrebbe essere una classe astratta. Proprio perché C# ti permette di definire le proprietà nelle interfacce, non significa che dovresti usarle. È un cattivo design. – Odys

+6

@odyodyodys - Non sono sicuro di essere d'accordo sul fatto che questo sia un cattivo design. Per favore spiega la tua logica? –

+3

@odyodyodys Sono d'accordo con zooone9243: Imp, dal punto di vista del progetto, non c'è differenza tra dichiarare una proprietà e dichiarare una coppia getter/setter (che è pratica comune per le interfacce). – MartinStettner

7

Non c'è niente di sbagliato nel creare un campo public. Ricorda però che creare getter/setter con i campi private non è incapsulamento. IMO, Se non ti interessa le altre funzionalità di un Property, potresti anche renderlo public.

41

Una differenza enorme che è spesso trascurato e non è menzionata in nessuna altra risposta: sovrascrivendo. È possibile dichiarare le proprietà virtuali e sovrascriverle mentre non è possibile fare lo stesso per i campi dei membri pubblici.

9

Un altro vantaggio delle proprietà auto-implementate su campi pubblici è che è possibile rendere privati ​​o protetti gli accessor set, fornendo la classe di oggetti in cui è stato definito un controllo migliore rispetto a quello dei campi pubblici.

0

Una cosa che trovo molto utile così come tutto il codice e le ragioni di test è che se è una proprietà vs un campo è che l'IDE di Visual Studio mostra i riferimenti per una proprietà ma non un campo.

Problemi correlati