2009-06-26 10 views
12

Il mio progetto contiene un numero elevato di classi con proprietà il cui campo di supporto è contrassegnato in sola lettura in quanto sono impostati solo in fase di costruzione. Per questioni di stile, mi piace usare le proprietà automatiche poiché elimina un sacco di codice di codice e incoraggia l'uso del membro della proprietà piuttosto che del campo di supporto. Tuttavia, quando si utilizza una proprietà automatica, perdo la "readonlyness" del mio campo di supporto. Capisco il compilatore/runtime è in grado di approfittare di alcuni miglioramenti delle prestazioni quando un campo è contrassegnato in questo modo, quindi mi piacerebbe essere in grado di marcare la mia auto-proprietà come sola lettura, qualcosa di simile:È possibile forzare una proprietà automatica per utilizzare un campo di backup di sola lettura?

[ReadOnly] 
public string LastName { get; } 

piuttosto che

private readonly string _LastName; 
public string LastName 
{ 
    get 
    { 
     return _LastName; 
    } 
} 

C'è qualche meccanismo già disponibile per farlo? In caso contrario, il guadagno prestazionale dal backing field personalizzato è di sola lettura davvero utile?

L'esposizione del campo come pubblica è un'altra opzione, suppongo, non sembra giusto esporre un campo in questo modo. vale a dire

public readonly string LastName; 
+1

Sono d'accordo che sembra sbagliato esporre un campo pubblico di sola lettura. Se dovesse mai essere necessario passare a una proprietà in un secondo momento, la modifica comprometterebbe la compatibilità. –

+2

Come hanno correttamente notato le risposte, no, non c'è modo di farlo adesso. Questa è una funzionalità richiesta frequentemente ed è sicuramente in cima alla lista di possibili nuove funzionalità per ipotetiche versioni future della lingua. Personalmente mi piacerebbe avere un intero set di funzionalità correlate che incoraggiano la programmazione in uno stile immutabile; questo sarebbe solo uno di loro. –

risposta

13

non ho paura, ma si può fare questo:

public string LastName { get; private set; } 

Non abbastanza buono come readonly, ma non troppo male.

+0

'' readonly stringa Foo {get {return "bar";} set;} 'e' stringa Foo {get {return "bar";}} 'equivalente? –

4

No non lo è e se fosse la funzionalità sarebbe inutile senza modifiche significative.

Un campo di sola lettura può essere impostato in modo verificabile solo da un costruttore. Una proprietà auto-implementata può essere impostata solo dal setter generato. Questi sono requisiti incompatibili e produrranno codice non verificabile.

Sì, si potrebbe potenzialmente rendere il compilatore abbastanza intelligente da ignorare il setter e passare direttamente al campo di supporto nel costruttore. Ma nel setter stesso sarebbe ancora non verificabile. Il compilatore dovrebbe ometterlo dal codice generato poiché produrrà una proprietà di sola lettura. Questo produce un'altra contraddizione perché avresti ancora bisogno di fare una dichiarazione di assegnazione contro la proprietà.

Foo() { 
    SomeProperty = "somevalue"; 
} 

In questo caso il codice sembra chiamare un setter su una proprietà. Ma in realtà non c'è un setter da chiamare dal momento che deve essere omesso dal codice finale.

EDIT

Questo non sta dicendo che non può essere fatto. Può, ma richiederebbe un po 'di lavoro da C#.

In particolare, dovrebbero fornire un modo per impostare il campo di appoggio di una proprietà che non può avere un setter. Ci sono diversi modi in cui ciò potrebbe essere fatto.

  • Dare agli utenti l'accesso al campo di appoggio di una proprietà auto-implementato
  • Consentire la sintassi stile setter, anche se non v'è alcuna setter e lasciare che il compilatore traduce in un accesso di campo sotto il cofano
  • Invent qualche nuova sintassi

Non sto dicendo che alcune di queste sono buone opzioni, solo possibilità di fare funzionare questo tipo di funzionalità.

+0

Avresti bisogno di una sintassi alternativa per questo, ma mi piacerebbe che fosse fattibile. Aggiungerà una risposta con esso ... –

+0

@ Sono d'accordo, ho modificato la mia risposta per dire "modifica significativa" – JaredPar

+0

+1 per andare a lunghezze per spiegare perché. Abbastanza interessante. – jasper

1

Preferisco il vero campo di supporto readonly, poiché questo garantisce che non sto cambiando quel campo di supporto dopo la costruzione.

1

No e no. Non c'è modo di farlo e non c'è alcun guadagno in termini di prestazioni per supportare i campi di sola lettura.

+0

Ho capito che 'static readonly' consente al JIT di fare alcune ottimizzazioni, come non fare mai copie del valore. – JulianR

+0

@ JulianR - Per quanto ne so, non ci sono vantaggi di prestazioni. Vedi http://stackoverflow.com/questions/277010/what-are-the-benefits-to-marking-a-field-as-readonly-in-c –

+2

Non si tratta di prestazioni, si tratta di codifica sicura. –

8

No, sfortunatamente non c'è modo di farlo. Personalmente ci sono due cose che penso manchino dalle proprietà implementate automaticamente in C# - un valore predefinito (che credo sarà in VB10) e proprietà readonly che possono essere impostate solo nel costruttore. In altre parole, mi piacerebbe essere in grado di fare:

public class Foo 
{ 
    public string Tag { get; internal set; } = "Default value"; 

    // The "readonly" would imply "private" as it could only 
    // be set from a constructor in the same class 
    public int Value { get; readonly set; } 

    public Foo() 
    { 
     // Valid to set property here, but nowhere else 
     Value = 20; 
    } 
} 

Come detto Jared, questo significherebbe cambiare le chiamate del compilatore per il setter di proprietà in semplici assegnazioni dei campi, e fare in modo che si sono verificati solo nel costruttore.

Ciò renderebbe la scrittura di tipi immutabili più semplice. Purtroppo la situazione non migliorerà nel C# 4. Speriamo di ottenere qualcosa del genere per C# 5 ...

+0

Nel frattempo, si preferisce l'uno rispetto all'altro? Sembra che sia la proprietà automatica setter-less sia l'implementazione del campo di back-ground forniscono un'implementazione immutabile. Dopo è solo questione di stile? – JadeMason

+5

Mi attengo personalmente a un campo di supporto di sola lettura a meno che non si tratti di codice throw-away. Mi piace sapere che è * correttamente * immutabile, anche se accidentalmente provo a impostarlo all'interno del mio tipo. –

+0

Eugh! Come può un setter essere di sola lettura? Forse public readonly int Valore {get; impostato; } –

3

A partire da C# 6.0 la risposta è sì. Il tuo esempio può essere scritto come sotto, e il compilatore genera automaticamente un campo di sola lettura dietro la proprietà. Questa è chiamata una proprietà auto-solo getter.

public string LastName { get; } 

Da https://msdn.microsoft.com/en-us/magazine/dn879355.aspx

Getter sola auto-proprietà sono disponibili in entrambe le strutture e le classi dichiarazioni, ma sono particolarmente importanti per le strutture a causa della linea guida di miglior pratica che le strutture essere immutabili . Piuttosto che la sei o più righe necessarie per dichiarare una proprietà di sola lettura e inizializzare prima di C# 6.0, ora una dichiarazione a riga singola e l'assegnazione all'interno del costruttore sono tutto ciò che è necessario. Pertanto, la dichiarazione di strutture immutabili ora non è solo il modello di programmazione corretto per le strutture, ma anche lo schema più semplice, una modifica molto apprezzata da una sintassi precedente in cui la codifica richiedeva uno sforzo maggiore.

Problemi correlati