Differenza in C # tra diversi stili getter


154

A volte vedo abbreviazioni nelle proprietà per il getter. Ad esempio quei due tipi:

public int Number { get; } = 0

public int Number => 0;

Qualcuno può dirmi se ci sono differenze tra quei due. Come si comportano? Sono entrambi di sola lettura?

Risposte:


266

Sì, entrambi sono di sola lettura, ma c'è una differenza. Nel primo, c'è un campo di supporto che viene inizializzato su 0 prima dell'esecuzione del costruttore. È possibile modificare il valore solo nel costruttore , proprio come un normale campo di sola lettura. Il getter stesso restituisce semplicemente il valore del campo.

Nel secondo, il getter restituisce solo 0 ogni volta, senza campo coinvolto.

Quindi, per evitare di utilizzare qualsiasi proprietà implementata automaticamente o membri con corpo di espressione, abbiamo:

Prima versione

private readonly int _number = 0;
public int Number { get { return _number; } }

Seconda versione

public int Number { get { return 0; } }

Un esempio più chiaro della differenza potrebbe essere visto in questo modo:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

Se si crea un singolo oggetto, la sua CreationTimeproprietà darà sempre lo stesso risultato, poiché è memorizzato in un campo di sola lettura, inizializzato sulla costruzione dell'oggetto. Tuttavia, ogni volta che accedi alla CurrentTimeproprietà, ciò causerà DateTime.UtcNowuna valutazione, quindi otterrai un risultato potenzialmente diverso.


23
Si noti che la seconda versione non restituisce sempre lo stesso valore. Un buon esempio è se torni random.NextInt(). La prima versione lo valuterà una volta e avrà sempre lo stesso valore. Il secondo restituirà un nuovo valore ogni volta.

248

Una differenza è quando 0viene valutato: al momento della creazione dell'oggetto o quando viene utilizzata la proprietà.

Puoi vederlo meglio con le proprietà DateTime:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

La Startproprietà continua a tornare nello stesso momento (di quando è stata creata l'istanza), mentre Nowcambia per riflettere l'ora corrente.

Spiegazione :

La prima versione ("Start") fornisce un valore iniziale che può anche essere sovrascritto dal costruttore. Quindi questo viene valutato solo una volta.
La seconda versione ("Now") fornisce l'espressione che sarà il "getter" di questa proprietà. Quindi questo viene valutato ogni volta che viene letta la proprietà. Non esiste nemmeno un campo di supporto che il costruttore possa sovrascrivere.


26
Questa è la distinzione più importante che penso.
Matteo,

14
La risposta accettata definisce più precisamente la differenza nel codice di esempio, ma questo spiega una differenza più utile nelle due strutture.
Kamil Drakari,

3
Caspita, hai ottenuto più voti rispetto al famoso Jon Skeet stesso.
machine_1,

21

Queste sono le funzionalità del linguaggio C # 6.

Primo esempio

public int Number { get; } = 0

Il primo esempio è una proprietà automatica solo getter . Il campo di supporto di una proprietà automatica solo getter viene implicitamente dichiarato di sola lettura.

Secondo esempio

public int Number => 0;

E il secondo esempio sono i corpi di espressione su membri di funzioni simili a proprietà . Si noti che non esiste alcuna getparola chiave: è implicito nell'uso della sintassi del corpo dell'espressione.

Entrambi sono di sola lettura.


5
... ma come spiega Jon Skeet, puoi cambiare il valore restituito dal primo.
Martin Bonner supporta Monica il

2
@MartinBonner ... ma solo nel costruttore.
Dennis Kuypers,

5
o, come sempre, attraverso la riflessione (minore nitpicking)
Marco Mp
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.