Auto-proprietà C # 3.0: utile o no? [chiuso]


155

Nota: questo è stato pubblicato quando stavo iniziando C #. Con la conoscenza del 2014, posso davvero dire che le proprietà automatiche sono tra le cose migliori che siano mai successe al linguaggio C #.

Sono abituato a creare le mie proprietà in C # usando un campo privato e uno pubblico:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Ora, con .NET 3.0, abbiamo ottenuto le proprietà automatiche:

public string Title { get; set; }

So che questa è una domanda più filosofica / soggettiva, ma c'è qualche motivo per usare queste proprietà automatiche se non dal salvare cinque righe di codice per ciascun campo? La mia lamentela personale è che quelle proprietà mi nascondono cose e non sono un grande fan della magia nera.

In effetti, il campo privato nascosto non viene nemmeno visualizzato nel debugger, il che è OK dato che le funzioni get / set non fanno nulla. Ma quando voglio implementare effettivamente qualche logica getter / setter, devo usare comunque la coppia privata / pubblica.

Vedo il vantaggio di salvare un sacco di codice (uno contro sei righe) senza perdere la possibilità di cambiare la logica getter / setter in un secondo momento, ma poi posso già farlo semplicemente dichiarando un campo pubblico "Titolo stringa pubblica" senza la necessità di {get; impostato; }, risparmiando così anche più codice.

Quindi, cosa mi sto perdendo qui? Perché qualcuno dovrebbe effettivamente voler usare le proprietà automatiche?


86
"La mia lamentela personale è che quelle proprietà mi nascondono cose e non sono un grande fan della magia nera." Eh? Sei consapevole che il compilatore ti nasconde sempre una tonnellata, giusto? A meno che tu non stia scrivendo assembly (o più precisamente, gli 1 e gli 0 effettivi per il tuo codice), TUTTO ciò che scrivi ti nasconde delle cose.
Charles Boyung,

Risposte:



62

Sì, salva solo il codice. È molto più facile da leggere quando ne hai un sacco. Sono più veloci da scrivere e più facili da mantenere. Il salvataggio del codice è sempre un buon obiettivo.

È possibile impostare diversi ambiti:

public string PropertyName { get; private set; }

In modo che la proprietà possa essere modificata solo all'interno della classe. Questo non è davvero immutabile in quanto è ancora possibile accedere al setter privato attraverso la riflessione.

A partire da C # 6 puoi anche creare readonlyproprietà reali , ovvero proprietà immutabili che non possono essere modificate al di fuori del costruttore:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

Al momento della compilazione diventerà:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

In classi immutabili con molti membri questo risparmia molto codice in eccesso.


"Quindi non perdi alcuna funzionalità." come li debug?
wal

2
@wal - cosa c'è da fare per il debug? Da quel punto di vista hai a che fare essenzialmente con le variabili membro.
Keith,

6
@wal: puoi inserire un punto di interruzione su di essi, proprio come puoi accedere a una variabile membro, non puoi semplicemente entrarci. Ma perché dovresti farlo? Ciò che le proprietà automatiche fanno effettivamente è sia banale che generato automaticamente, se hai dei bug in un posto che è estremamente improbabile che siano.
Keith,

3
potremmo aver bisogno di portarlo fuori da Keith. :)
wal,

1
Ma ok, supponi di avere molte chiamate setter a myObj.Title ... vuoi vedere dove il valore cambia da "testo" a null, cioè un breakpoint condizionale. come lo fai? non puoi nemmeno impostare un breakpoint sul setter
wal,

45

I tre grandi svantaggi dell'utilizzo dei campi anziché delle proprietà sono:

  1. Non è possibile eseguire il databind su un campo mentre è possibile su una proprietà
  2. Se inizi utilizzando un campo, non puoi successivamente (facilmente) cambiarlo in una proprietà
  3. Esistono alcuni attributi che è possibile aggiungere a una proprietà che non è possibile aggiungere a un campo

7
"Se inizi a utilizzare un campo, non puoi successivamente (facilmente) cambiarlo in una proprietà", scusa ma perché?
Homam,

6
@Homam Principalmente, qualsiasi codice utente che utilizza la riflessione sui campi si romperà, poiché dovrebbero passare dall'uso di FieldInfo a PropertyInfo.
WCWedin

8
@Homam Inoltre, la modifica di un campo in una proprietà interrompe la compatibilità binaria, richiedendo la ricompilazione di tutti gli utenti del campo.
Odrade,

1
a parte i problemi di ricompilazione e riflessione, è molto facile incapsulare i campi utilizzando Visual Studio: Ctrl-R + E ti permetterà di trasformare un campo in una proprietà con getter / setter appropriati. (oppure fai clic con il pulsante destro del mouse sul campo, ricodifica, incapsula il campo).
JoeBrockhaus,

I campi @Hommam sono valori (sono variabili) e le proprietà no. Le cose che potrebbero essere state compilate quando era un campo potrebbero non essere quando sono proprietà.
Segna

29

Personalmente adoro le proprietà automatiche. Cosa c'è di sbagliato nel salvare le righe di codice? Se vuoi fare cose in getter o setter, non c'è problema a convertirle in proprietà normali in seguito.

Come hai detto, potresti usare i campi e se volessi aggiungere loro la logica in un secondo momento, li convertiresti in proprietà. Ma questo potrebbe presentare problemi con qualsiasi uso della riflessione (e forse altrove?).

Inoltre, le proprietà ti consentono di impostare diversi livelli di accesso per il getter e il setter che non puoi fare con un campo.

Immagino sia uguale alla parola chiave var. Una questione di preferenze personali.


29

Da Bjarne Stroustrup, creatore di C ++:

Non mi piacciono particolarmente le lezioni con molte funzioni get e set. Questo è spesso un'indicazione che non avrebbe dovuto essere una classe in primo luogo. È solo una struttura di dati. E se è davvero una struttura di dati, rendila una struttura di dati.

E tu sai cosa? Ha ragione. Quante volte stai semplicemente avvolgendo i campi privati ​​in get e set, senza realmente fare nulla all'interno di get / set, semplicemente perché è la cosa "orientata agli oggetti" da fare. Questa è la soluzione di Microsoft al problema; sono fondamentalmente campi pubblici ai quali puoi impegnarti.


2
Penso davvero che questo dovrebbe avere più punti. Troppe persone vedono le proprietà automatiche come un semaforo verde per la scrittura di classi orribilmente incapsulate (o per nulla incapsulate) che sono poco più che un campo pubblico glorificato. Naturalmente questo è più un problema con il modo in cui le persone usano lo strumento piuttosto che con lo strumento stesso, ma penso che sia importante menzionare quando si discute delle proprietà in generale.
Sara,

18

Una cosa che nessuno sembra aver menzionato è come le proprietà automatiche non sono purtroppo utili per oggetti immutabili (di solito strutture immutabili). Perché per quello dovresti davvero fare:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(dove il campo è inizializzato nel costruttore tramite un parametro passato e quindi è di sola lettura.)

Quindi questo ha dei vantaggi rispetto a una semplice get/ private setautoproperty.


Se si dispone di una struttura che modifica qualsiasi proprietà, si ottiene una nuova struttura. Questo sarebbe un problema solo se volessi un tipo di riferimento immutabile internamente - non riesco a vedere un motivo per cui ne avresti mai bisogno.
Keith,

@Keith: la tua prima frase sembra effettivamente errata.
Domenic,

3
Non public string Title { get; private set; }risulterebbe esattamente nella stessa cosa? Ovviamente potresti cambiarlo dall'interno della classe, ma se lo fai hai altri problemi ...: p
Svish

2
@Svish - con questo argomento la parola chiave di sola lettura in C # non dovrebbe mai essere usata perché il suo uso significherebbe nascondere questi "diversi problemi"
Zaid Masud,

2
Intendo solo che da un punto di vista API esterno, non farebbe molta differenza. Quindi, se lo si desidera, è possibile utilizzare le proprietà automatiche. La cosa migliore sarebbe ovviamente se tu potessi fare qualcosa del generepublic string Title { get; private readonly set; }
Svish,

12

Creo sempre proprietà anziché campi pubblici perché è possibile utilizzare proprietà in una definizione di interfaccia, non è possibile utilizzare campi pubblici in una definizione di interfaccia.


8

Le proprietà automatiche sono una magia nera quanto qualsiasi altra cosa in C #. Una volta che ci pensi in termini di compilazione fino a IL piuttosto che essere espansa in una normale proprietà C # prima è molta meno magia nera di molti altri costrutti di linguaggio.


5

Uso sempre le proprietà automatiche. Prima di C # 3 non potevo essere infastidito da tutta la digitazione e invece utilizzavo solo variabili pubbliche.

L'unica cosa che mi manca è riuscire a farlo:

public string Name = "DefaultName";

Devi spostare i valori predefiniti nei tuoi costruttori con proprietà. noioso :-(


4
Con gli inizializzatori di proprietà automatica di C # 6 sarai presto in grado di farlo: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz,

5

Penso che qualsiasi costrutto intuitivo che riduca le righe di codice sia un grande vantaggio.

Questi tipi di funzionalità sono ciò che rende linguaggi come Ruby così potenti (che e funzionalità dinamiche, che aiutano anche a ridurre il codice in eccesso).

Ruby lo ha sempre avuto:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

2

L'unico problema che ho con loro è che non vanno abbastanza lontano. La stessa versione del compilatore che ha aggiunto proprietà automatiche, ha aggiunto metodi parziali. Il motivo per cui non hanno messo insieme i due è oltre me. Un semplice "parziale su <nome proprietà> modificato" avrebbe reso queste cose davvero utili.


È possibile inserire più metodi parziali all'interno di un altro metodo. Creare un modello automatico di qualche tipo per loro sarebbe confuso.
Matthew Whited,

2

È semplice, è breve e se si desidera creare una vera implementazione all'interno del corpo della proprietà da qualche parte lungo la linea, non si romperà l'interfaccia esterna del tipo.

Così semplice.


1

Una cosa da notare qui è che, per la mia comprensione, questo è solo zucchero sintattico sull'estremità di C # 3.0, il che significa che l'IL generato dal compilatore è lo stesso. Sono d'accordo sull'evitare la magia nera, ma comunque, meno righe per la stessa cosa di solito è una buona cosa.


1

A mio avviso, dovresti sempre utilizzare le proprietà automatiche anziché i campi pubblici. Detto questo, ecco un compromesso:

Inizia con un campo interno utilizzando la convenzione di denominazione che utilizzeresti per una proprietà. Anche tu la prima volta

  • bisogno di accedere al campo dall'esterno del suo assemblaggio, o
  • è necessario collegare la logica a un getter / setter

Fai questo:

  1. rinominare il campo
  2. renderlo privato
  3. aggiungere una proprietà pubblica

Il tuo codice cliente non dovrà cambiare.

Un giorno, tuttavia, il tuo sistema crescerà e lo decomponi in assiemi separati e soluzioni multiple. Quando ciò accade, tutti i campi esposti torneranno a perseguitarti perché, come ha detto Jeff, cambiare un campo pubblico in una proprietà pubblica è una rottura dell'API .


0

Uso CodeRush, è più veloce delle proprietà automatiche.

Per fare questo:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Richiede un totale di otto sequenze di tasti.


5
Se tengo premuto CTRL e V, posso incollare un sacco di cose, / molto rapidamente /, ma ciò non lo rende "migliore". Come risponde alla domanda originale?
JBR Wilkinson,

0

Bene, con i frammenti di codice, una proprietà automatica con lo stesso nome sarebbe un totale di sette sequenze di tasti;)


0

@Domenic: non capisco .. non puoi farlo con le proprietà automatiche ?:

public string Title { get; }

o

public string Title { get; private set; }

È a questo che ti riferisci?


Puoi (il secondo; il primo non verrà compilato), ma il campo non è immutabile all'interno del tuo oggetto.
Domenic,

Avvertenza, solo le strutture sono immutabili se contrassegnate di sola lettura, le classi sono semplicemente non assegnabili.
Guvante,

0

La mia più grande lamentela con le proprietà automatiche è che sono progettate per risparmiare tempo, ma spesso trovo che devo espanderle in proprietà complete in seguito.

Ciò che manca a VS2008 è un rifrattore di proprietà automatica esplodi .

Il fatto che abbiamo un refactor di campo incapsulato rende il mio modo di lavorare più veloce per usare solo i campi pubblici.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.