> As it is always stated that value type is allocated on stack, while reference types are on managed heap.
A lot of books state this. It is an oversimplification. The truth is:
1. Reference types are allocated on the managed heap.
2. Value types that are local variables or method parameters are
allocated on the stack. This includes references to reference types
(which are, themselves, just values).
3. Value types that are members of a reference type (for example the
"int"s that form part of an object's state) are allocated along with
and in-line with all of the other data for the reference type, on the
managed heap.
Your assumption about a value type that contains a reference to a
string is correct: the values that make up the value type will be
allocated wherever that value type is allocated. If it is a local
variable or a method parameter, on the stack. If it is a member in a
class definition, then on the heap with the rest of the data for the
class.
The value type will contain as part of its value a reference to the
string, which will be allocated on the managed heap.
Remember that strings are immutable, so one cannot make a change to the
string and have all value types that reference it change together,
although your assumption that all value types point to the same string
on the heap would be true (depending upon how the string was
constructed and how its reference is placed in the struct).
Your theory works out better if you choose something other than a
string. Take, for example, a value type that is a Measure:
public struct Measure
{
private decimal _quantity;
private UnitOfMeasure _units;
public Measure(decimal quantity, UnitOfMeasure units)
{
...
}
}
Assuming that UnitOfMeasure is a reference type, then the struct will
contain: a decimal value, and a reference. If multiple Measures are
constructed pointing to the same UnitOfMeasure, then they all contain
the same reference to the same unit of measure object on the managed
heap.
If the UnitOfMeasure class were mutable (a bad idea, in this case, but
say it were) then a change to a unit of measure object would have an
effect in all Measure structs that point to it, just as you surmised.
That's why I made my UnitOfMeasure class immutable. :)