2009-03-17 14 views
127

mi rendo conto che sembra essere un duplicato del What is the difference between a Field and a Property in C#? ma la mia domanda ha una leggera differenza (dal mio punto di vista):Differenza tra proprietà e campo in C# 3.0 +

Una volta che so che

  • Non userò la mia classe con "tecniche che funzionano solo sulle proprietà" e
  • Non userò il codice di convalida nel getter/setter.

C'è qualche differenza (tranne lo stile/quelli di sviluppo futuri), come un qualche tipo di controllo nell'impostazione della proprietà?

C'è qualche differenza supplementare tra:

public string MyString { get; set; } 

e

public string myString; 

(Mi rendo conto che, che la prima versione richiede C# 3.0 o superiore e che il compilatore non creare i campi privati .)

+0

possibile duplicato di [getter e setter implementati automaticamente rispetto ai campi pubblici] (http://stackoverflow.com/questions/111461/auto-implemented-getters-and-setters-vs-public-fields) – nawfal

risposta

108

Incapsulamento.

Nella seconda istanza hai appena definito una variabile, nella prima è presente un getter/setter attorno alla variabile. Quindi se decidi di convalidare la variabile in un secondo momento, sarà molto più semplice.

Inoltre si fanno vedere in modo diverso in Intellisense :)

Edit: Aggiornamento per PO domanda aggiornato - se si vuole ignorare gli altri suggerimenti qui, l'altro motivo è che non è semplicemente una buona progettazione OO. E se non hai una buona ragione per farlo, sempre scegli una proprietà su una variabile pubblica/campo.

+8

Perché è più facile? Cosa mi impedisce di trasformare un campo in una proprietà e aggiungere un campo di supporto privato? In che modo questo influenza il codice di chiamata? –

+27

@Serge - Influisce sul codice già compilato. Ad esempio, se si sta sviluppando una libreria utilizzata da più applicazioni, la modifica di un campo in una proprietà in tale libreria richiederebbe una ricompilazione di ciascuna applicazione. Se si trattasse di una proprietà, è possibile aggiornare la proprietà senza preoccupazioni. –

+0

Sono totalmente d'accordo con te, io uso sempre le proprietà. Ero solo curioso di una possibile differenza – p4bl0

7

Il primo:

public string MyString {get; set; } 

è una struttura; il secondo (public string MyString) indica un campo.

La differenza è che alcune tecniche (associazione dati ASP.NET per istanze) funzionano solo sulle proprietà e non sui campi. Lo stesso vale per la serializzazione XML: solo le proprietà sono serializzate, i campi non sono serializzati.

+8

Sbagliato. Serializzazione XML FA SERIALIZZARE i campi pubblici. –

+2

Forse. Ma quando crei un'origine dati oggetto da una classe, puoi solo utilizzare le proprietà, non i campi. (A meno che non ho fatto qualcosa di sbagliato: P) – Svish

+0

Buono è quello di ASCIUGARE;) ma scrivo ancora una volta, mi piace un forte ruolo di proprietà nel linguaggio C#. È molto meglio implementato rispetto a Java (di conseguenza sin dall'inizio) Molte, forse tutte le soluzioni .net funzionano solo sulle proprietà. WPF, ASPX e altro. –

40

Un paio rapidi, evidenti differenze

  1. una proprietà può avere parole chiave accesso.

    public string MyString { get; private set; } 
    
  2. Una proprietà può essere ignorata nei discendenti.

    public virtual string MyString { get; protected set; } 
    
+0

mmh .. nr 2 è interessante .. non ci ho pensato – p4bl0

+1

aggiungi il controllo delle versioni a quello :) –

13

La differenza fondamentale è che un campo è una posizione in memoria in cui vengono memorizzati i dati del tipo specificato. Una proprietà rappresenta una o due unità di codice che vengono eseguite per recuperare o impostare un valore del tipo specificato.L'uso di questi metodi di accesso è sintatticamente nascosto utilizzando un membro che sembra comportarsi come un campo (in quanto può apparire su entrambi i lati di un'operazione di assegnazione).

3

Le proprietà e i campi possono, in molti casi, sembrare simili, ma non lo sono. Esistono limitazioni alle proprietà che non esistono per i campi e viceversa.

Come altri hanno menzionato. È possibile rendere una proprietà di sola lettura o di sola scrittura rendendola accessoria privata. Non puoi farlo con un campo. Le proprietà possono anche essere virtuali, mentre i campi non possono.

Pensare alle proprietà come zucchero sintattico per le funzioni getXXX()/setXXX(). Questo è il modo in cui sono implementati dietro le quinte.

145

I campi e le proprietà hanno lo stesso aspetto, ma non lo sono. Le proprietà sono metodi e in quanto tali esistono alcune cose che non sono supportate per le proprietà e alcune cose che possono accadere con le proprietà ma mai nel caso dei campi.

Ecco un elenco di differenze:

  • campi può essere utilizzato come input per out/ref argomenti. Le proprietà non possono.
  • Un campo produrrà sempre lo stesso risultato quando viene chiamato più volte (se si eliminano problemi con più thread). Una proprietà come DateTime.Now non è sempre uguale a se stessa.
  • Le proprietà possono generare eccezioni: i campi non lo faranno mai.
  • Le proprietà possono avere effetti collaterali o richiedere molto tempo per l'esecuzione. I campi non hanno effetti collaterali e saranno sempre veloci come ci si può aspettare dal tipo specificato.
  • Proprietà supporto diverso accessibilità per getter/setter - campi non lo fanno (ma i campi possono essere fatti readonly)
  • Quando si utilizza riflessione le proprietà ei campi sono trattati come diversi MemberTypes in modo che si trovano in modo diverso (GetFields vs GetProperties per esempio)
  • Il compilatore JIT può trattare l'accesso alle proprietà in modo molto diverso rispetto all'accesso al campo. Può tuttavia essere compilato con codice nativo identico, ma lo scopo della differenza è lì.
+11

Nota comunque che molti di questi punti dovrebbero * non * essere differenze se vengono utilizzate buone pratiche. Cioè, le proprietà in realtà non dovrebbero mai avere effetti collaterali, né dovrebbero impiegare molto tempo per essere eseguite. – Noldorin

+13

@Noldorin: sono d'accordo, ma sfortunatamente * dovrebbe * è la parola chiave qui. Con i campi che il comportamento è garantito. Non sto dicendo che dovresti usare i campi, ma è importante essere consapevoli delle differenze semantiche. –

+4

Sì, abbastanza giusto. I programmatori principianti non hanno la minima idea di queste cose, purtroppo ... – Noldorin

10

Gli accessi sono più che campi. Altri hanno già fatto notare alcune importanti differenze e ne aggiungerò un'altra.

Le proprietà partecipano alle classi di interfaccia. Ad esempio:

interface IPerson 
{ 
    string FirstName { get; set; } 
    string LastName { get; set; } 
} 

Questa interfaccia può essere soddisfatta in diversi modi. Per esempio:

class Person: IPerson 
{ 
    private string _name; 
    public string FirstName 
    { 
     get 
     { 
      return _name ?? string.Empty; 
     } 
     set 
     { 
      if (value == null) 
       throw new System.ArgumentNullException("value"); 
      _name = value; 
     } 
    } 
    ... 
} 

In questa implementazione stiamo proteggendo sia la classe Person di entrare in uno stato non valido, così come il chiamante di ottenere nulla fuori dalla proprietà non assegnato.

Ma potremmo spingere ulteriormente il design. Ad esempio, l'interfaccia potrebbe non occuparsi del setter.E 'del tutto legittimo dire che i consumatori di IPerson interfaccia sono interessati solo a ottenere la proprietà, non in impostazione:

interface IPerson 
{ 
    string FirstName { get; } 
    string LastName { get; } 
} 

Precedente attuazione dei soddisfa classe Person questa interfaccia. Il fatto che consenta al chiamante di impostare anche le proprietà è privo di significato dal punto di vista dei consumatori (che consumano IPerson). Ulteriori funzionalità della realizzazione concreta viene preso in considerazione, ad esempio, costruttore:

class PersonBuilder: IPersonBuilder 
{ 
    IPerson BuildPerson(IContext context) 
    { 

     Person person = new Person(); 

     person.FirstName = context.GetFirstName(); 
     person.LastName = context.GetLastName(); 

     return person; 

    } 
} 

... 

void Consumer(IPersonBuilder builder, IContext context) 
{ 
    IPerson person = builder.BuildPerson(context); 
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName); 
} 

In questo codice, i consumatori non conosce setter di proprietà - non è affar suo saperlo. Il consumatore ha bisogno solo di getter e riceve i getter dall'interfaccia, cioè dal contratto.

Un'altra tutto valido attuazione IPerson sarebbe una classe persona immutabile ed una corrispondente fabbrica persona:

class Person: IPerson 
{ 
    public Person(string firstName, string lastName) 
    { 

     if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName)) 
      throw new System.ArgumentException(); 

     this.FirstName = firstName; 
     this.LastName = lastName; 

    } 

    public string FirstName { get; private set; } 

    public string LastName { get; private set; } 

} 

... 

class PersonFactory: IPersonFactory 
{ 
    public IPerson CreatePerson(string firstName, string lastName) 
    { 
     return new Person(firstName, lastName); 
    } 
} 
... 
void Consumer(IPersonFactory factory) 
{ 
    IPerson person = factory.CreatePerson("John", "Doe"); 
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName); 
} 

In questo codice di esempio consumatore una volta non è a conoscenza di riempire le proprietà. Il consumatore tratta solo i getter e l'implementazione concreta (e la logica di business dietro di esso, come testare se il nome è vuoto) è lasciata alle classi specializzate - costruttori e fabbriche. Tutte queste operazioni sono assolutamente impossibili con i campi.

1

C'è un'altra importante differenza tra campi e proprietà.

Quando si utilizza WPF, è possibile associare solo proprietà pubbliche. Il binding a un campo pubblico sarà non lavoro. Questo è vero anche quando non si implementa INotifyPropertyChanged (anche se si dovrebbe sempre).

+0

Buono è ESSERE ASCIUTTO;) ma scrivo ancora una volta, mi piace un forte ruolo di proprietà nel linguaggio C#. È molto meglio implementato rispetto a Java (di conseguenza sin dall'inizio) Molte, forse tutte le soluzioni .net funzionano solo sulle proprietà. WPF, ASPX e altro ancora. –

0

È necessario utilizzare sempre le proprietà anziché i campi per qualsiasi campo pubblico. Ciò garantisce che la libreria abbia la capacità di implementare l'incapsulamento per qualsiasi campo se necessario in futuro senza rompere i codici esistenti. Se si sostituiscono i campi con le proprietà in le librerie esistenti quindi tutti i moduli dipendenti che utilizzano la libreria devono essere ricostruiti.

+0

"always" è una parola a dura parola. In C# (meglio che in Java) la proprietà ha una posizione forte, è (probabilmente senza eccezione) principale/metodo di "binding" in ASP, WPF e altri. Ciononostante, posso immaginare il design con il campo che nessuna proprietà ha senso (a volte) –

0

Tra le altre risposte ed esempi, penso che questo esempio sia utile in alcune situazioni.

Per esempio diciamo di avere un OnChangeproperty come segue:

public Action OnChange { get; set; } 

Se si desidera utilizzare i delegati di quanto è necessario cambiarlo OnChange-field in questo modo:

public event Action OnChange = delegate {}; 

In tale situazione proteggiamo il nostro campo da accessi indesiderati o modifiche.

Problemi correlati