Помогите разобраться.
В книге написано:
Типы, допускающие пустые значения, фактически являются ссылочными
типами, и переменные этих типов создаются в динамической памяти". Но
если мы говорим о ссылочных типах, то переменные с адресом на объект
хранятся же в стеке, а сами объекты в куче.
Почему тогда здесь говорится, что переменные создаются в динамической памяти.
В книге ошибка или я чего-то не понимаю?
Ответ
Это не ошибка, это утверждение, далекое от реальности + кривой перевод.
Есть типы значений (value types), есть ссылочные типы (reference types).
Переменная value type хранит значение прямо в себе. Для value type после a = b вы получите "в a лежит то же значение, что и в b". Если у вас есть value type Point, то
Point b = new Point(5, 5);
Point a = b; // скопировали значение b в a
a.X = 1;
Console(b.X) // 5!
Переменная reference type хранит в себе ссылку на объект. Для reference type после a = b вы получите "а ссылается на тот же объект, что и b"
Point b = new Point(5, 5);
Point a = b; // а теперь указывает (ссылается) на тот же объект Point, что и B
a.X = 1;
Console(b.X) // 1!
Это единственное различие.
По поводу хранения.
Переменная - это конструкция уровня языка. Переменные не могут "создаваться в динамической памяти". С точки зрения языка нет разницы между стеком и "динамической памятью".
Стек - это особенность реализации, и компилятор языка сам решает, где хранить значение переменной.
Значения переменных могут хранится в стеке или в динамической памяти. Под значением подразумевается непосредственно значение для value type, и ссылка (адрес) - для reference type. Значения локальных переменных обычно хранятся в стеке.
Но при этом утверждения "переменные value types храняться в стеке" или "переменные с адресом на объект хранятся в стеке, а сами объекты в куче" в принципе неверны.
Смотрите:
Локальная переменная типа value type. Значение (5) скорее всего будет лежать в стеке:
int i = 5;
Локальная переменная типа reference type. Значение (адрес объекта) скорее всего будет лежать в стеке. Сам объект - в куче.
object o = new object();
Пока вроде сходится?
Переменная типа value type - поле класса. Объект вместе со всеми полями лежит в куче. Значение переменной value type (5) лежит .. в куче!
class A { public int somefield; }
//.....
A a = new A();
a.somefield = 5; // положили значение 5 внутрь объекта в куче
Локальная переменная типа value type, на которую есть замыкание (упоминание переменной внутри анонимного метода). Объявление ничем не отличается от (1), это точно такая же локальная переменная типа int. Но замыкание создает анонимный класс, и переменная на самом деле будет храниться как поле класса. В куче:
int i = 5;
// чуть ниже в том же методе
Action someAction = () => { Console.WriteLine(i); };
Так что если взять цитату из книги (насколько я понял, это "Microsoft Visual C#. Подробное руководство"), и разобрать по частям, то:
Все переменные типов значений создаются в стеке.
Неверно, см. 3 и 4 выше!
Все переменные ссылочных типов (объекты) создаются в динамической памяти (хотя сами ссылки находятся в стеке)
Неверно, переменная ссылочного типа != объект.
Типы, допускающие пустые значения, фактически являются ссылочными типами, и переменные этих типов создаются в динамической памяти.
Неверно, речь о nullable types (например, int?), а они - структуры, value types. Локальные переменные типа int? в случае (1) лежат прямо в стеке - по сути, в стеке лежит структура, в которой одно поле - это флаг "есть ли значение", а второе - само значение.
Комментариев нет:
Отправить комментарий