2010-02-22 19 views
73

Sto leggendo CLR tramite C# di Jeffery Richter e si dice che una struttura è un tipo di valore e non può essere ereditata. Perchè no? Qualche ragione tecnica? O filosofici?Perché una struttura C# non può essere ereditata?

+1

Forse più una questione di una risposta, ma tutte le strutture ereditano System.ValueType e se si guarda con riflettore, System.ValueType è una classe astratta :) Tutte le strutture ereditano esso. Penso che sarebbe utile se le risposte a questa domanda chiarissero questo. – Marek

+3

@Marek: Leggi il secondo paragrafo della mia risposta qui per chiarimenti su questo: http://stackoverflow.com/questions/1978589/why-do-struct-need-to-be-boxed/1978597#1978597 Per riassumere, ereditare da 'ValueType' non ha implicazioni strutturali per l'istanza di struct. Infatti, un valore struct non è realmente un 'System.ValueType' per quanto riguarda il runtime (cioè in IL, non puoi passare un' int' a un metodo che prende un 'ValueType' senza usare esplicitamente la casella' 'istruzione). Lo è solo una struttura in scatola (che è un tipo di riferimento). –

risposta

77

Modifica: Ci sono serie preoccupazioni editoriali su questo post, a quanto pare. Vedi la sezione commenti.

Un po 'di entrambi.

Filosoficamente, funziona - ci sono classi, che sono il "vero" building block per programmazione orientata agli oggetti, e ci sono le strutture, che sono tipi di dati leggeri per lo stoccaggio, consentono oggetto simile metodo chiede familiarità e convenienza.

Tecnicamente, essendo un "tipo di valore" significa che l'intera struttura, tutto il suo contenuto, viene (solitamente) memorizzata ovunque sia presente una variabile o un membro di quel tipo. Come parametro locale o parametro di funzione, significa in pila. Per le variabili membro, ciò significa memorizzato interamente come parte dell'oggetto.

Come esempio (primario) del motivo per cui l'ereditarietà è un problema, considerare se lo storage è interessato a un livello basso se si consente alle strutture di avere sottotipi con più membri. Qualsiasi cosa memorizzasse quel tipo di struttura occuperebbe una quantità variabile di memoria in base a quale sottotipo finiva con il contenere, il che sarebbe un incubo di allocazione. Un oggetto di una data classe non avrebbe più una dimensione costante e conosciuta al momento della compilazione e lo stesso sarebbe vero per i frame stack di qualsiasi chiamata di metodo. Ciò non si verifica per gli oggetti che dispongono di memoria allocata nell'heap e hanno invece riferimenti a dimensioni costanti a quella memoria nello stack o all'interno di altri oggetti.

Questa è solo una spiegazione intuitiva e di alto livello - Vedi commenti e altre risposte per informazioni più dettagliate e più dettagliate.

+0

Grazie, Jesse. La tua spiegazione mi ha dato delle scintille. Per quanto ne so, l'OOP ha un costo. Se c'è solo "ref-type" e tutto accade nell'heap, la cui gestione è molto meno efficiente dello stack, le prestazioni saranno scarse. Quindi arriva il cosiddetto "valore-tipo" che vive nello stack per prestazioni migliori, ed è a causa del luogo dell'allocazione e del paradigma dell'utilizzo della memoria che rende il valore-type sigillato. – smwikipedia

+0

... e se riusciamo a capire un paradigma nuovo di zecca dell'uso della memoria oltre allo stack e all'heap, potrebbero sorgere nuovi tipi di dati. – smwikipedia

+0

Per quanto riguarda i nuovi paradigmi dell'uso della memoria ... È dubbio. :) Qualsiasi altro paradigma di utilizzo della memoria è probabile che sia sovrapposto a stack o heap allocazione o entrambi. (Ad esempio chiusure in linguaggi funzionali, che potrebbero valere il tuo tempo per capire.) –

32

Perché è il modo in cui le strutture sono rappresentate in .NET. Sono tipi di valore e i tipi di valore non hanno un puntatore della tabella del metodo che consente l'ereditarietà.

+17

Si potrebbe aggiungere: E il motivo per cui non hanno un puntatore della tabella dei metodi è perché i tipi di valore sono progettati per essere il più leggeri possibile. – bitbonk

+9

Tranne che le strutture * possono * implementare interfacce e un puntatore della tabella del metodo viene usato per chiamarle ... – Bevan

+1

Esistono diversi modi in cui le strutture possono supportare l'ereditarietà senza bisogno di informazioni sul tipo di istanza: (1) dicendo che l'effetto * solo * di «FooStruct: BarStruct» sarebbe che un tipo generico vincolato a «BarStruct» sarebbe in grado di accedere direttamente ai membri (* compresi i campi *) di quel tipo; (2) dicendo che qualsiasi tipo 'FooStruct: BarStruct' deve essere contrattualmente vincolato ad usare i suoi campi ereditati in modo tale che un' BarStruct' formato copiando i campi ereditati di un 'FooStruct esistente 'deve essere un' BarStruct' valido e ... – supercat

14

È possibile trovare le risposte a SO Domanda Why are .NET value types sealed? rilevanti. In esso, si riferisce a @logicnpECMA 335, in cui si afferma:

8.9.10 Tipo di valore eredità

  • [...]
  • sarà sigillato per evitare di affrontare le complicazioni di valore affettare.
  • Le regole più restrittive qui specificate consentono un'implementazione più efficiente senza compromettere seriamente la funzionalità.
+1

Dove per "senza compromettere seriamente la funzionalità", intendevano chiaramente "compromettendo severamente la funzionalità". –

Problemi correlati