2016-04-22 21 views
12

Qual è la differenza tra una proprietà con un setter omesso e una proprietà con un setter privato?setter omesso vs setter privato?

public string Foo { get; private set; } 

vs

public string Foo { get; } 
+5

Semplice: una proprietà con un setter omesso ** non ha un setter **. Non è possibile riassegnare la proprietà al di fuori della dichiarazione di proprietà o di un costruttore. – BoltClock

+3

Come mai questa domanda sta facendo salire i voti? Ho pensato che fosse banale ... – Alex

+3

avviso duplicato: http: //stackoverflow.com/questions/3847832/understanding-private-setters, http://stackoverflow.com/questions/4948816/getters-setters-and-properties- best-practices-java-vs-c-sharp – Tushar

risposta

19

In C# 6, get; solo le proprietà sono impostabili solo dal costruttore. Da qualsiasi altra parte, è di sola lettura.

Una proprietà con un private set; può essere impostata ovunque all'interno di tale classe.

+0

Capisco. Mi chiedo perché esista la funzionalità di avere setter omesso. Quale sarebbe la ragione per dichiarare una proprietà impostabile solo dal costruttore ma dai metodi all'interno della classe? – Fred

+0

Per evitare di impostare questa proprietà per errore da qualche parte all'interno di quel metodo? –

7

dall'esterno della classe, ma non cambierà nulla se si utilizza questa sintassi:

public string Foo { get; } 

ma non sarà in grado di aggiornare Foo all'interno la classe, ad eccezione del costruttore, per farlo, è necessario il setter privato:

public string Foo { get; private set; } 
+1

* non sarà possibile aggiornare Foo all'interno della classe * Sbagliato. Puoi solo impostarlo nel costruttore. –

+0

@PatrickHofman ringrazia per il commento, non lo sapevo prima! –

+0

È interessante che ogni risposta abbia questa parte in particolare sbagliata, e continua a fare voti, mentre la mia ha indicato questo fin dall'inizio e non ha ottenuto alcun voto ... –

3

Una proprietà con un setter omesso viene letta solo ovunque tranne il costruttore della classe, incluso all'interno della classe.

Una proprietà con un setter privato viene letta solo esternamente (anche in sottoclassi), ma scrivibile internamente.

3

Il setter private è - beh - un metodo set privato che è possibile utilizzare solo all'interno della classe.

Il omesso setter rende la proprietà readonly. Quindi puoi solo impostare il valore di questa proprietà nei tuoi costruttori o tramite un'inizializzazione statica.

5

La differenza è che il codice generato produrrà un campo di sola lettura nel secondo caso e ovviamente la proprietà non avrà un setter.

Facciamo un esempio reale:

public class Test 
{ 
    public Test(string name) { Name = name; } 
    public string Name { get; private set; } 
} 

il compilatore compilare questo in questo modo:

public class Test 
{ 
    private string <Name>k__BackingField; 
    public Test(string name) 
    { 
     <Name>k__BackingField = name; 
    } 
    public string Name 
    { 
     get { return <Name>k__BackingField; } 
     private set { <Name>k__BackingField = value; } 
    } 
} 

Come si può vedere il compilatore ha automagicamente riscritto il codice per avere un campo di supporto per la proprietà. Il nome del campo sarà quel nome criptico, che è legale .NET ma non C#, il che significa che non puoi mai scrivere codice C# in conflitto con tale membro generato automaticamente.

Fondamentalmente, le proprietà automatiche in C# sono solo zucchero sintattico per una proprietà con un campo di supporto, la proprietà effettiva che si sta compilando ha ancora un campo di supporto, non è necessario scriverlo esplicitamente.

Come si può vedere, inoltre, ha riscritto automaticamente il costruttore per scrivere direttamente nel campo. Nota che questo verrà fatto ovunque all'interno di questa classe in cui la proprietà è scritta, dal momento che non vi è alcuna possibilità che ogni codice personalizzato sia comunque intromesso.

Ora cerchiamo di rimuovere il setter dalla proprietà e vediamo cosa succede:

public class Test 
{ 
    private readonly string <Name>k__BackingField; 
    public Test(string name) 
    { 
     <Name>k__BackingField = name; 
    } 
    public string Name 
    { 
     get { return <Name>k__BackingField; } 
    } 
} 

Si noti che il campo è ora di sola lettura, e di nuovo, ovviamente, il setter è passato dalla proprietà pure.

Quindi questo è in realtà il modo migliore ora per creare tipi semplici con veri proprietà di sola lettura, non solo è la struttura in sé non scrivibile, ma il campo di supporto viene anche in sola lettura che significa che stai ora meglio attrezzata per scrivere facilmente tipi immutabili.

+0

Interessante, suppongo che questo si applichi anche alle proprietà statiche di sola lettura (cioè quando dichiara solo un auto-getter) –

+0

Sì, 'statico 'non ha importanza a questo proposito –

+0

Non ho provato a vedere cosa stava succedendo con questo caso (sia di istanza o proprietà private con solo un 'get;'). Quindi, non dichiarerò manualmente più campi 'readonly'; P (a meno che non abbia bisogno di non incapsularli, ma l'accesso ai campi di classe senza incapsulamento è ancora una cattiva pratica di codifica). –