Question:
Help me to understand.
The book says:
Types that allow null values are actually reference types, and variables of these types are created in dynamic memory. "But if we are talking about reference types, then variables with an address to an object are stored on the stack, and the objects themselves are stored on the heap.
Why then it says here that variables are created in dynamic memory.
Is there a mistake in the book or am I missing something?
Answer:
This is not a mistake, this is a statement that is far from reality + a crooked translation.
There are value types, there are reference types.
The variable value type stores the value directly in itself. For value type after a = b
you get " a
contains the same value as b
". If you have value type Point
, then
Point b = new Point(5, 5);
Point a = b; // скопировали значение b в a
a.X = 1;
Console(b.X) // 5!
The variable reference type stores a reference to an object. For reference type after a = b
you will get " а
refers to the same object as b
"
Point b = new Point(5, 5);
Point a = b; // а теперь указывает (ссылается) на тот же объект Point, что и B
a.X = 1;
Console(b.X) // 1!
This is the only difference.
About storage.
A variable is a language level construct. Variables cannot be "created in dynamic memory". From a language point of view, there is no difference between a stack and "dynamic memory".
The stack is an implementation feature, and it is up to the language compiler to decide where to store the value of a variable.
Variable values can be stored on the stack or in dynamic memory. The value means directly the value for the value type, and the reference (address) for the reference type. The values of local variables are usually stored on the stack.
But at the same time, the statements "variables of value types are stored on the stack" or "variables with an address to an object are stored on the stack, and the objects themselves are on the heap" are fundamentally incorrect.
See:
-
Local variable of type value type. The value (
5
) will most likely be on the stack:int i = 5;
-
Local variable of type reference type. The value (address of the object) will most likely be on the stack. The object itself is on the heap.
object o = new object();
As long as it fits?
-
A variable of type value type is a class field. The object, along with all the fields, is on the heap. The value of the variable value type (5) lies .. in the heap!
class A { public int somefield; } //..... A a = new A(); a.somefield = 5; // положили значение 5 внутрь объекта в куче
-
A local variable of type value type that has a closure (mention of a variable inside an anonymous method). The declaration is no different from (1), it is exactly the same local variable of type
int
. But the closure creates an anonymous class and the variable will actually be stored as a field of the class. In heap:int i = 5; // чуть ниже в том же методе Action someAction = () => { Console.WriteLine(i); };
So if you take a quote from a book (as far as I understand, this is "Microsoft Visual C #. A detailed guide"), and parse it in parts, then:
All value type variables are created on the stack.
Wrong, see 3 and 4 above!
All variables of reference types (objects) are created in dynamic memory (although the references themselves are on the stack)
Wrong, reference type variable != object.
Nullable types are actually reference types, and the variables of these types are created in heap memory.
Wrong, we are talking about nullable types (for example, int?
), and they are structures, value types. Local variables of type int?
in case (1) they lie directly on the stack – in fact, the stack contains a structure in which one field is the "is there a value" flag, and the second is the value itself.