2011-10-09 6 views
18

Un campo di sola lettura deve essere utilizzato quando si dispone di una variabile che sarà nota all'oggetto-instatiation che non dovrebbe essere modificata in seguito.readonly-fields come target dai costruttori di sottoclasse

Tuttavia non è consentito assegnare campi di sola lettura da costruttori di sottoclassi. Questo non funziona nemmeno se la superclasse è astratta.

Qualcuno ha una buona spiegazione del perché questa non è una buona idea, o manca nella C# languange?

abstract class Super 
{ 
    protected readonly int Field; 
} 

class Sub : Super 
{ 
    public Sub() 
    { 
     this.Field = 5; //Not compileable 
    } 
} 

PS: Ovviamente si può raggiungere lo stesso risultato con l'assegnazione dei campi di sola lettura in un costruttore protetto nella superclasse.

+1

Anche l'errore del compilatore non è accurato: 'Errore 68 Non è possibile assegnare un campo di sola lettura (tranne in un costruttore o un inizializzatore di variabile)' – nicodemus13

risposta

12

L'unico motivo che posso vedere per questo è perché "è stato appena concepito in questo modo", come per i spec:

incarichi diretti a sola lettura campi possono avvenire solo come parte di tale dichiarazione o in un costruttore di istanze o un costruttore statico nella stessa classe .

Il punto di essere sola lettura è che non può essere modificata, se classi derivate potrebbe modificare allora questo non sarebbe più vero e violare l'incapsulamento (modificando la struttura interna di un'altra classe).

+1

è vero. Ma è ancora inappropriato per le classi astratte? Forse a causa della possibilità di più sottoclassi. – philipshield

+2

Forse non è appropriato, e forse non sapremo mai il motivo esatto per quella decisione di progettazione. –

+0

Non vedo perché sia ​​inappropriato per le classi astratte, poiché possono avere costruttori, quindi i campi di sola lettura funzionerebbero. – pauloya

10
public class Father 
{ 
    protected readonly Int32 field; 

    protected Father (Int32 field) 
    { 
     this.field = field; 
    } 
} 

public class Son : Father 
{ 
    public Son() : base(5) 
    { 

    } 
} 

Si può provare qualcosa di simile, invece!

+0

Oh, non ho visto! È stato un montaggio? – renatoargh

+0

Sì, ho detto che nella mia domanda :) Inoltre, alexm ha pubblicato la stessa risposta esatta circa 10 minuti fa. – philipshield

+2

Non era una modifica, ma non importa! È una soluzione ordinata – philipshield

0

suppongo che il motivo principale è una complessità aggiuntiva per tutte le implementazioni .NET lingua

anche, c'è sempre una soluzione semplice:

abstract class Super 
{ 
    protected readonly int Field; 

    protected Super(int field) 
    { 
      this.Field = field; 
    } 
} 


class Sub : Super { 
    public Sub():base(5) 
    { 
    } 

}

0

avrei modellare questo da un proprietà astratta/virtuale in C#.

Secondo me è una soluzione migliore rispetto a un costruttore che include ogni singolo campo di sola lettura come parametro Per uno perché il compilatore è in grado di inline questo come bene e anche perché la soluzione costruttore avrà questo aspetto nella classe derivata:

class Sub : Super { 
    public Sub() : base(5) { } // 5 what ?? -> need to check definition of super class constructor 
} 

inoltre che potrebbe non funzionare se si dispone già di un costruttore che prende un singolo int valore.

0

Preferirei utilizzare il costruttore protetto in superclasse (come menzionato da alexm), a portata di mano con commenti xml. Questo dovrebbe eliminare il problema che ha detto DonAndre nel suo commento sul codice.