Proprietà automatizzata con solo getter, può essere impostata, perché?


96

Ho creato una proprietà automatizzata:

public int Foo { get; } 

Questo è solo getter. Ma quando costruisco un costruttore, posso cambiare il valore:

public MyClass(string name)
{
    Foo = 5;
}

Perché è possibile, anche se si tratta di solo acquisto?


In realtà non usa un setter (perché non ne ha uno). Imposta direttamente il campo sottostante (che ci è nascosto, motivo per cui è necessario utilizzare il nome della proprietà)
Dennis_E

14
A cosa serve una proprietà se non può mai essere inizializzata / impostata? Yacoub Massad ha risposto perfettamente
Vikhram

Risposte:


123

Questa è una nuova funzionalità di C # 6, "Getter-only auto-properties", nota anche come "Auto-Property Initializers for Read-Only Properties" come discusso in questo articolo della rivista MSDN "C #: The New and Improved C # 6.0" di Mark Michaelis e nella bozza di specifica del linguaggio C # 6.0 .

Il setter del campo di sola lettura è accessibile solo nel costruttore, in tutti gli altri scenari il campo è ancora di sola lettura e si comporta come prima.

Questa è una sintassi comoda per ridurre la quantità di codice che è necessario digitare e per rimuovere la necessità di dichiarare esplicitamente una variabile a livello di modulo privato per contenere il valore.

Questa funzionalità è stata considerata importante poiché, dall'introduzione delle proprietà implementate automaticamente in C # 3, le proprietà modificabili (quelle con getter e setter) erano diventate più veloci da scrivere rispetto a quelle immutabili (quelle con solo un getter), il che significa che le persone erano essere tentati di utilizzare proprietà modificabili per evitare di dover digitare il codice per un campo di supporto solitamente richiesto per le proprietà di sola lettura. Sono disponibili ulteriori discussioni sulle proprietà implementate automaticamente nella sezione pertinente della Guida per programmatori Microsoft C # .

Questo post del blog, "# 1,207 - C # 6.0 - Inizializzatori di proprietà automatica per proprietà di sola lettura" di Sean Sexton ha una buona spiegazione ed esempio come segue:

Prima di C # 6.0, se si voleva una proprietà di sola lettura (immutabile), si usava in genere un campo di supporto di sola lettura inizializzato nel costruttore, come mostrato di seguito.

public class Dog 
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }

    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

In C # 6.0 è possibile usare proprietà implementate automaticamente per implementare una proprietà di sola lettura. A tale scopo, utilizzare un inizializzatore di proprietà automatica. Il risultato è molto più chiaro rispetto all'esempio precedente, in cui dovevamo dichiarare esplicitamente un campo di supporto.

public class Dog
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;

    public Dog(string name)
    {
        Name = name;
    }
}

Maggiori dettagli possono essere trovati anche nel repository dotnet Roslyn su GitHub :

Le proprietà automatiche possono ora essere dichiarate senza un setter.

Il campo di supporto di una proprietà automatica solo getter è implicitamente dichiarato di sola lettura (sebbene ciò sia importante solo per scopi di riflessione). Può essere inizializzato tramite un inizializzatore sulla proprietà come nell'esempio sopra. Inoltre, è possibile assegnare una proprietà solo getter nel corpo del costruttore del tipo dichiarante, che fa sì che il valore venga assegnato direttamente al campo sottostante:

Si tratta di esprimere i tipi in modo più conciso, ma nota che rimuove anche un'importante differenza nel linguaggio tra tipi mutabili e immutabili: le proprietà automatiche erano una scorciatoia disponibile solo se eri disposto a rendere la tua classe mutabile, e quindi la tentazione di default a quello è stato fantastico. Ora, con le proprietà automatiche solo getter, il campo di gioco è stato livellato tra mutevole e immutabile.

e nella bozza di specifica del linguaggio C # 6.0 (NB: la specifica del linguaggio è definitiva per quanto riguarda Microsoft, ma deve ancora essere approvata come standard EMCA / ISO , da cui la 'bozza'):

Proprietà implementate automaticamente

Una proprietà implementata automaticamente (o auto-proprietà in breve), è una proprietà non astratta non esterna con corpi di accesso solo punto e virgola. Le proprietà automatiche devono avere una funzione di accesso get e facoltativamente possono avere una funzione di accesso set.

Quando una proprietà viene specificata come una proprietà implementata automaticamente, un campo di supporto nascosto è automaticamente disponibile per la proprietà e le funzioni di accesso vengono implementate per leggere e scrivere in quel campo di supporto. Se la proprietà auto non ha una funzione di accesso impostata, il campo di supporto viene considerato di sola lettura (campi di sola lettura). Proprio come un campo di sola lettura, una proprietà automatica solo getter può anche essere assegnata nel corpo di un costruttore della classe che lo racchiude. Tale assegnazione viene assegnata direttamente al campo di supporto di sola lettura della proprietà.

Una proprietà automatica può opzionalmente avere un property_initializer, che viene applicato direttamente al campo sottostante come variable_initializer (inizializzatori di variabili).


1
Questo è un design stupido. Questo dovrebbe essere un errore in fase di compilazione se impostato in una posizione in cui la proprietà è considerata di sola lettura.
Shiv

La stranezza per me è che c'è ancora un errore del compilatore che dice CS0200 C# Property or indexer cannot be assigned to -- it is read onlyquando si usa una proprietà normale. Le "proprietà automatiche solo getter" sono considerate di sola lettura o no?
Kyle Delaney,

24

Questa è una nuova funzionalità in C # 6 che consente di creare proprietà di sola lettura e inizializzare i relativi valori dal costruttore (o inline quando vengono dichiarati).

Se provi a cambiare il valore di questa proprietà al di fuori del costruttore, ti darebbe un errore di compilazione.

È di sola lettura, nel senso che una volta inizializzato il suo valore (inline o all'interno del costruttore), non è possibile modificarne il valore.


Allora, qual è la spiegazione? Qual è la definizione di a getter?
Noam B.

16

Se non fosse possibile inizializzare la proprietà di sola lettura dal costruttore (o un inizializzatore di proprietà automatica), allora sarebbe inutile, poiché restituirebbe sempre il valore predefinito per il suo tipo (0 per i numeri, null per i tipi di riferimento ). La stessa semantica applicata ai campi di sola lettura in tutte le versioni C #.

Per definire una vera proprietà solo getter (che non può essere inizializzata dal costruttore), è necessario specificare cosa restituisce come parte della definizione:

public int Foo { get { return 5; } }

O, più concisamente in C # 6:

public int Foo => 5;

Non del tutto vero, le proprietà di sola lettura sono molto utili per incapsulare alcune condizioni nel codice. Puoi scrivere un'istruzione if e quasi qualsiasi codice per valutare altre proprietà o condizioni e restituire un valore appropriato ogni volta che leggi la proprietà
sebagomez

3
@sebagomez: Non sono sicuro di aver capito il tuo punto - non è quello che ho dimostrato nel mio esempio?
Douglas

5

"Proprietà implementate automaticamente in sola lettura"

Prima di tutto ci tengo a precisare che la struttura piace

public string FirstName { get; }

È noto come "proprietà implementate automaticamente in sola lettura"

Per verificarlo puoi eseguire e controllare il codice sopra con Visual Studio. Se si modifica la versione della lingua da C # 6.0 a C # 5.0, il compilatore genererà la seguente eccezione. La funzionalità "proprietà implementate automaticamente in sola lettura" non è disponibile in C # 5. Utilizzare la versione della lingua 6 o successiva.

per modificare la versione in linguaggio C # visitare qui

Ora vengo alla tua seconda domanda

“Questo è solo getter. Ma quando costruisco un costruttore, posso modificare il valore "

Microsoft introduce le "proprietà implementate automaticamente in sola lettura" nella logica di sola lettura. Come sappiamo che la parola chiave "readonly" è disponibile da C # 1.0. usiamo la parola chiave "readonly" come modificatore su un campo e quel campo può essere assegnato in 2 modi o al momento della dichiarazione o in un costruttore nella stessa classe.

Allo stesso modo il valore di "proprietà implementate automaticamente in sola lettura" può essere assegnato in 2 modi

Way1 (al momento della dichiarazione):

public string FirstName { get; } = "Banketeshvar";

Way2 (in un costruttore nella stessa classe)

Person()
{
 FirstName  = "Banketeshvar";
}

Proprietà di sola lettura

Se stai cercando una proprietà di sola lettura, scegli questo

public string FullName => "Manish Sharma";

ora non è possibile assegnare il valore della proprietà "FullName" dal costruttore. Se provi a farlo, verranno generate le seguenti eccezioni

"Impossibile assegnare la proprietà o l'indicizzatore" Person.FullName "- è di sola lettura"


2
nota che FullName => "foo bar" verrà valutato OGNI VOLTA.
juFo

4

La funzionalità di proprietà automatica è stata aggiunta alla lingua durante il rilascio di C # 3.0. Ti consente di definire una proprietà senza alcun campo di supporto, tuttavia è comunque necessario utilizzare il costruttore per inizializzare queste proprietà automatiche su un valore non predefinito. C # 6.0 introduce una nuova funzionalità chiamata inizializzatore di proprietà automatico che consente di inizializzare queste proprietà senza un costruttore come di seguito:

In precedenza, è richiesto un costruttore se si desidera creare oggetti utilizzando una proprietà auto e inizializzare una proprietà auto su un valore non predefinito come di seguito:

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}

Ora in C # 6.0, la possibilità di usare un inizializzatore con la proprietà auto significa che non è richiesto alcun codice costruttore esplicito.

public string Foo { get; } = "SomeString";

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

Puoi trovare maggiori informazioni su questo qui


1

Una variabile dichiarata readonlypuò essere scritta all'interno di un costruttore, ma nei linguaggi che rispettano l'attributo, non può essere modificata dopo la restituzione del costruttore. Quel qualificatore è stato fornito come caratteristica del linguaggio perché è spesso necessario per i campi i cui valori varieranno in base ai parametri del costruttore (il che significa che non possono essere inizializzati prima dell'avvio del costruttore) ma non dovranno cambiare dopo il ritorno dei costruttori, ma è stato utilizzabile solo per variabili esposte come campi. La semantica dei readonlycampi -qualified in molti casi sarebbe stata perfetta per i membri pubblici, tranne per il fatto che spesso è meglio per le classi esporre i membri, anche quelli immutabili, come proprietà piuttosto che come campi.

Proprio come esistono proprietà automatiche di lettura-scrittura per consentire alle classi di esporre proprietà modificabili con la stessa facilità dei campi ordinari, esistono proprietà automatiche di sola lettura per consentire alle classi di esporre proprietà immutabili con la stessa facilità readonlydei campi qualificati. Proprio come i readonlycampi -qualified possono essere scritti in un costruttore, così anche con le proprietà get-only.

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.