2012-03-23 7 views
5

So che la mia domanda sembra stupida ma sono confuso. Apprezzo se qualcuno mi chiarisce questo per me.Relazione tra classe System.Object e Structures

So che le strutture, ad es. Int32, sono tipi di valore e vengono istanziati su stack mentre le classi sono tipi di riferimento e vengono istanziati su heap. So anche che tutte le strutture derivano dal tipo System.Object, che è una classe. Mi chiedo come sia possibile che il supertipo, System.Object, sia un tipo di riferimento e il sottotipo, Int32, sia un tipo di valore? Dove dovrei cercare di capire come funziona?

+7

lettura correlati: [lo stack è un dettaglio di implementazione] (http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation -detail.aspx) – Heinzi

+2

Possibile duplicato di http://stackoverflow.com/questions/1682231/how-do-valuetypes-derive-from-object-referencetype-and-still-be-valuetypes – daryal

+0

Questo è noto al compilatore –

risposta

11

So che le strutture, ad es. Int32, sono tipi di valore e vengono istanziati su stack mentre le classi sono tipi di riferimento e vengono istanziati su heap.

Tu non sai che, perché per essere classificato come conoscenza una credenza deve essere vero. Questa convinzione non è certamente vera, anche se molte persone lo credono.

I tipi di valore sono a volte allocati nello stack. I riferimenti sono talvolta allocati nello stack e fanno riferimento alla memoria allocata nell'heap. I tipi di valore sono a volte allocati nell'heap. (E naturalmente tipi di valore e riferimenti possono anche essere allocati in registri che non sono né pila né mucchio.)

Nei determina quale memorizzazione viene allocato mucchio e ciò che viene allocato sullo stack è le durate conosciuti del deposito, non che tipo di cosa è. Se una variabile è nota per essere di breve durata, può essere assegnata allo stack; se non si sa che è di breve durata, allora deve essere assegnato sullo heap.

So anche che tutte le strutture derivano dal tipo System.Object, che è una classe. Mi chiedo come sia possibile che il supertipo, System.Object, sia un tipo di riferimento e il sottotipo, Int32, sia un tipo di valore?

Sospetto che tu non capisca cosa significhi "ereditare da" in primo luogo se questo ti confonde. Quando diciamo che System.Int32, un tipo di valore, eredita da System.Object, un tipo di riferimento, intendiamo che tutti i membri di Object sono anche membri di Int32. L'oggetto ha un metodo "ToString". Questo è un membro di Object. Pertanto, Int32 ha anche un metodo "ToString", poiché Int32 eredita da Object.

Questo è tutto che significa ereditarietà. Sospetto che tu creda che l'ereditarietà significhi qualcos'altro e che qualunque cosa "qualcosa" precluda i tipi di valore dall'estendere i tipi di riferimento. Qualsiasi credenza tu abbia che ti fa pensare che i tipi di valore non possano ereditare dai tipi di riferimento è chiaramente falso, poiché ovviamente lo fanno.

Sono interessato a scoprire quali sono le cose false che le persone credono nei linguaggi di programmazione; cosa pensi che erroneamente sia vero riguardo alla relazione di ereditarietà che impedirebbe ai tipi di valore di derivare da tipi di riferimento?

Si consiglia di leggere e comprendere tutti questi articoli:

http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

http://blogs.msdn.com/b/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx

http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

http://ericlippert.com/2011/09/19/inheritance-and-representation/

E bonus extra, questo potrebbe anche essere utile a voi :

http://blogs.msdn.com/b/ericlippert/archive/2012/01/16/what-is-the-defining-characteristic-of-a-local-variable.aspx

+5

Io non sono l'OP, ma penso che una credenza comune nell'eredità vada in questo modo: se crei un oggetto di tipo "Derivato", devi (in modo creativo) creare un oggetto di tipo "Base" che viene poi "aggiunto" con ogni altro tipo derivato finché non hai costruito "Derivato". (dopotutto, stiamo chiamando ogni costruttore di base della catena). Pertanto, per creare un 'Int32' devi creare un' Object' e quindi un tipo di riferimento. –

+0

Grazie, Eric. Stavo pensando esattamente a quello che Michael ha detto ed è stato in qualche modo strano per me. – Morteza

+3

@MichaelStum: la parola chiave è "concettualmente" - infatti, una costruzione di un int * concettualmente * è una costruzione prima di un oggetto. Ma * in pratica * non è quello che * in realtà * accade perché il sistema è stato impostato con cura in modo che * non * debba * accadere. –

2

Prima di tutto, la caratteristica distintiva dei tipi di valore non è dove sono memorizzati, ma come vengono passati ai metodi. Gli Struct sono passati per valore; questa è una copia dell'argomento creata e passata. Eventuali modifiche alla copia all'interno del metodo non influiscono sull'argomento effettivo (a meno che non condividano lo stesso riferimento) I tipi di riferimento vengono passati per riferimento; che è un puntatore all'argomento reale passato.

Sì, le strutture sono derivate da ValueType. E ValueType deriva da Object. Quindi, in definitiva le strutture derivano anche da Object. (Ad esempio, i metodi ToString(), ==, Equals(), GetHashCode() e forse alcuni altri sono definite nelle Object e quindi anche nelle struct di)

Tuttavia, la semantica di passaggio degli argomenti non sono definite nelle classi stessi; non c'è alcun codice all'interno della definizione di Object che dice "qualsiasi istanza dei miei sottotipi deve essere passata per riferimento" e non vi è alcun codice all'interno della definizione di ValueType che dice "ogni istanza dei miei sottotipi deve essere passata per valore". [Forse c'è un attributo speciale ma questo non conta] È responsabilità del compilatore onorarlo. (C'è del codice da qualche parte nei compilatori C# che dice "genera un codice tale che i discendenti di ValueType saranno passati per valore e altri saranno passati per riferimento")

Il blog di Eric Lippert è una risorsa fantastica su molte questioni su C#, e dovresti leggere il link @Heinzi fornito per ulteriori chiarimenti.