2010-01-04 7 views
9

Mi sto confondendo con ciò che accade nello stack e nell'heap in relazione alle proprietà del tipo di valore nelle classi.Restituire un tipo di valore da una proprietà

mia comprensione finora:

Quando si crea una classe con una struttura (tipo di valore) in questo modo:

class Foo 
{ 
    private Bar _BarStruct; 
    public Bar BarStruct 
    { 
    get {return _BarStruct; } 
    set {_BarStruct = value; } 
    } 
} 

private struct Bar 
{ 
    public int Number; 
    Bar() 
    { 
    Number = 1; 
    } 
    Bar(int i) 
    { 
    Number = i; 
    } 
} 

Se si crea un'istanza di classe in questo modo:

Foo fooObj = new Foo(); 

Lo stack e l'heap sarà simile al seguente:

https://i962.photobucket.com/albums/ae105/acardy/stackheap-1.jpg(https://i962.photobucket.com/albums/ae105/acardy/stackheap-1.jpg)

... dove la struttura della barra è incorporata nella classe Foo nell'heap. Questo ha senso per me, ma comincio a perdere quando consideriamo di modificare il numero intero nella classe BarStruct, all'interno di Foo Object. Ad esempio:

Foo fooObj = new Foo(); 
fooObj.BarStruct.Number = 1; 

quanto ho capito, questo dovrebbe ritorneremo una copia di BarStruct vivere in pila, il che significa che tutte le modifiche di un membro di BarStruct non sarebbero trasportati attraverso l'oggetto, che è il motivo l'ultima riga sopra dà un errore.

È giusto così?

Se è così, la mia domanda è, come mai un incarico come questo:

fooObj.BarStruct = new Bar(2); 

... è valido e cambia il valore mucchio? Sicuramente questo è solo cambiando il valore in pila ?? Inoltre, (a poco a poco) trovo così confuso il fatto che tu sia in grado di usare nuovo su un tipo di valore. Per me, new è per allocattazione sull'heap (come per C++) e sembra innaturale farlo per gli elementi in pila.

Quindi, solo per ripetere la domanda, sono corretto nel mio presupposto di cosa succede quando viene chiamata una proprietà contenente una struttura e perché è possibile assegnare una nuova struttura a una copia e tuttavia cambia ancora il riferimento sul mucchio?

Spero davvero che tutto abbia senso.

Urlo se avete bisogno di chiarimenti!

Ta,

Andy.

+0

@Andy, 1 bella domanda. Scommetto che se chiedi a 10 programmatori C# esperti, meno della metà saprebbe esattamente cosa sta succedendo qui. Le strutture sono complicate perché sembrano classi ma hanno importanti differenze. – Ash

risposta

10

Guardando a questo incarico:

fooObj.BarStruct = new Bar(2); 

L'assegnazione non cambia il valore sullo stack - è chiamando il setter per la proprietà.

In altre parole, mentre il vostro primo compito è equivalente a:

fooObj.get_BarStruct().Number = 1; // Bad 

il secondo è equivalente a:

fooObj.set_BarStruct(new Bar(2)); 

fa questo aiuto?

Si noti che l'assegnazione problematica diventa un non-problema se si rende immutabile il tipo di valore per iniziare, il che aiuta in generale, di fatto. I tipi di valore mutabili sono una pessima idea in C#; puoi metterti nei guai con loro.

In termini delle vostre aspettative di "nuovo" - cercate di non pensare in C++, in pratica. C# non è C++ e varie cose (distruttori, generici, comportamenti durante la costruzione) ti confondono se provi a scrivere in modo efficace C++ in C#. Una "nuova" istruzione crea una nuova istanza di un tipo, che si tratti di un tipo di valore o di un tipo di riferimento.

+0

In realtà, questo aiuta molto, davvero avrei dovuto pensarci un po 'più logicamente, ma spero che possa aiutare anche altri! :) Molte grazie! – Andy

+0

Jon, sono appena stato colto da questo usando System.Drawing.Rectangle e System.Drawing.Point quando ho provato a metterli nelle proese. Microsoft avrebbe dovuto davvero rendere queste strutture immutabili. – Ash

+0

@Ash: sono d'accordo. Le strutture mutevoli possono essere utili in un insieme di circostanze * molto * limitato, ma sono quasi sempre più pericolose che vantaggiose. –