2010-03-19 5 views
54

Ho trovato un argomento su MSDN che parla di sì, questo è possibile.È possibile la proprietà auto-implementata di sola lettura?

ho fatto un test che sembra rompere questa dichiarazione:

using System; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Foo f = new Foo("1"); 
      Console.WriteLine(f.Bar); // prints 1 
      f.Test("2"); 
      Console.WriteLine(f.Bar);// successfully prints 2 
     } 
    } 

    class Foo 
    { 
     public Foo(string b) 
     { 
      this.Bar = b; 
     } 

     public string Bar { get; private set; } 

     public void Test(string b) 
     { 
      // this would be impossible for readonly field! 
      // next error would be occur: CS0191 or CS0191 
      // A readonly field cannot be assigned to (except in a constructor or a variable initializer) 
      this.Bar = b; 
     } 
    } 
} 

Dove sbaglio?

+4

Penso che stiate testando il tipo sbagliato di sola lettura qui. Il tuo codice dice solo che non ti è permesso di impostare la proprietà Bar direttamente da qualsiasi luogo al di fuori della classe, né da sottoclassi (setter privato). I metodi della tua classe possono ancora cambiare la variabile se il setter è privato. – dbemerlin

+1

ummm ... che dire 'public readonly string Bar;'? – peterchen

+0

@dbemerlin: sto parlando di readonly nel senso della parola chiave. Non sui livelli di accesso. C'è un argomento appropriato su MSDN: http://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx. Penso che ci sia solo un tipo di sola lettura in C#. Tutto il resto è solo tutto il resto, non di sola lettura in C# :) – abatishchev

risposta

91

La risposta qui sotto è stato scritto nel 2010. In C# 6 (uscito nel 2015) si può scrivere sola lettura proprietà automaticamente implementati:

// This can only be assigned to in a constructor 
public int Foo { get; } 

Hai assolutamente ragione. Al momento, le proprietà implementate automaticamente di sola lettura sono attualmente impossibili. Rendere il privato setter non è la stessa cosa, indipendentemente da quello che alcuni libri e MSDN potrebbero dire :)

Se ho governato il mondo, questo non sarebbe il caso. Quando vedo alcuni dei progettisti di linguaggi allo NDC 2010 a giugno (per favore, vieni avanti!) Intendo cercare di persuadere, corrompere, persuadere e in genere fare un fastidio a me stesso fino a quando non sono d'accordo. Dopotutto, è solo una funzione wafer-thin.

Guardando tale articolo MSDN, il testo stesso non dice che si crea una proprietà di sola lettura automatica. Crea un tipo immutabile utilizzando una proprietà automatica e questo è corretto. I soli bit problematici sono i commenti che dicono

// Read-only properties. 

... che sono decisamente sbagliati. Il framework è d'accordo con noi:

var prop = typeof(Contact).GetProperty("Name"); 
Console.WriteLine(prop.CanWrite); // Prints True 
+1

Una caratteristica * wafer-thin * si traduce in molte settimane di lavoro: http://blogs.msdn.com/ericlippert/archive/2003/10/28/53298.aspx – Brian

+0

@Brian: Ecco perché sto andando dover persuadere, fare bridge, blandire ecc :) Ma rispetto a molte altre caratteristiche, credo che questo * sarebbe * piccolo. –

+26

Non devi convincerci che è una buona idea; sappiamo che è una buona idea. Le domande sono (1) è questa la migliore caratteristica possibile che possiamo fare dato il budget di tempo e denaro che abbiamo, e (2) possiamo spendere quel budget per risolvere un aspetto più generale, più difficile, meno "sottile" dell'immutabilità , di quali puntelli immutabili sono un caso speciale semplice?Ogni caratteristica di "scopo speciale" ristretto che aggiungiamo aumenta la complessità della grammatica; vogliamo assicurarci che stiamo ottenendo un buon valore in futuro per questa complessità aggiuntiva. –

1

Il set privato non è lo stesso di readonly.

Simile a metodi o campi, la parola chiave private rende la visibilità del setter a disposizione solo la classe stessa. Altri oggetti non possono usare il setter, ma i metodi della classe stessa possono chiamarlo liberamente. Quindi il tuo codice di prova viene compilato e funziona correttamente.

sembra oggetti esterni come una proprietà readonly, ma non è di sola lettura nella vera definizione.

8

La proprietà è di sola lettura al di fuori della classe Foo. Penso che sia quello a cui si sta lavorando.

ma non è lo stesso di marcatura una variabile con la parola chiave readonly.

6

È confuso. È necessario differenziare la lettura sola per il C# readonly (cosa significa la parola chiave).

  • di sola lettura: significano che nessuno all'esterno può scrivere direttamente, solo leggere.
  • C# readonly: è possibile scrivere solo nel costruttore, quindi mai più.
+0

Chiamerei "sola lettura" e "sola lettura in C#" – abatishchev

+2

@abatischchev c'è una parola chiave readonly in C#, che era ciò che intendevo –

+0

@persuade: Sì, ne sto parlando anche io. Voglio dire che qualcosa in C# non è di sola lettura senza parola chiave readonly. È meglio chiamarlo in qualche altro modo – abatishchev

4

No, non è possibile rendere una proprietà auto-implementata in sola lettura.Per la pagina si è collegato:

con proprietà auto-implementato, sia un get e set di accesso sono tenuti

Una sola lettura struttura non dispone di accesso set.

A property without a set accessor is considered read-only

1

La parola chiave ReadOnly, in C# e VB, fanno la stessa cosa se applicato a un campo. Fanno in modo che il campo sia assegnabile solo durante l'inizializzazione statica (se è contrassegnato come un campo statico/condiviso) o durante il costruttore.

C# non utilizza la parola chiave readonly per nient'altro.

La parola chiave ReadOnly in VB assume un significato diverso se applicata a una proprietà. In questo caso, significa semplicemente che non esiste un modo accettabile per assegnare alla proprietà pubblica (internamente, il campo di supporto può essere modificato da un altro codice interno, ovviamente).

1

Non è possibile creare una proprietà auto-implementata readonly. Se si tenta di compilare una classe con una proprietà di auto-implementato otterrete questo errore se non ha sia ottenere e impostare:

'ProjectName.ClassName.Property.get' deve dichiarare un corpo perché non è segnato astratto o extern. Le proprietà implementate automaticamente devono definire sia get che set accessors.

Con la frase che inizia con "Automatically" è la parte dell'errore di cui ci occupiamo.