Local Variable
Each local variable (i.e. one declared
in a method) is stored on the stack. That includes reference type variables -
the variable itself is on the stack, but remember that the value of a
reference type variable is only a reference (or null), not the object itself.
Method parameters count as local variables too, but if they are declared
with the ref modifier, they don't get their own slot, but share a slot with
the variable used in the calling code.
Instance variables
Instance variables for a reference type
are always on the heap. That's where the object itself "lives".
Instance variables for a value type are
stored in the same context as the variable that declares the value type. The
memory slot for the instance effectively contains the slots for each field
within the instance. That means (given the previous two points) that a struct
variable declared within a method will always be on the stack, whereas a
struct variable which is an instance field of a class will be on the heap.
Static Variable
Every static variable is stored on the
heap, regardless of whether it's declared within a reference type or a value
type. There is only one slot in total no matter how many instances are
created. (There don't need to be any instances created for that one slot to
exist though.) Note that this heap is separate from the normal garbage
collected heap - it's known as a "high frequency heap", and there's one per
application domain.
A Worked Example The above may
all sound a bit complicated, but a full example should make things a bit
clearer. Here's a short program which does nothing useful, but should
demonstrate the points raised above.
Sample Code
using System;
struct PairOfInts {
static int counter=0; public int a;
public int b;
internal PairOfInts (int x, int
y) { a=x;
b=y; counter++; }
}
class Test { PairOfInts
pair; string name;
Test (PairOfInts p, string s,
int x) { pair = p;
name = s; pair.a += x; }
static void Main()
{ PairOfInts z = new PairOfInts (1, 2);
Test t1 = new Test(z, "first", 1); Test t2 = new
Test(z, "second", 2); Test t3 = null;
Test t4 = t1; // XXX }
}
|