Особенности хранения данных в памяти. Ссылочные и простые типы данных. Область видимости переменных

Большинство программистов C# напрямую не сталкивается с подробностями размещения данных в памяти, подробные данные нужны только опытным программистам для оптимизации скорости работы программы. Но основы надо знать всем - сейчас поймете почему. Для любых данных нужно место в памяти компьютера. В некоторых языках вроде C и C++ программистам надо вручную выделять его при создании переменных и освобождать после завршения их использования, сталкиваясь с ошибками вроде утечек памяти.

В C# дела обстоят иначе. Для самых простых типов данных память компьютера выделяется автоматически, написав int counter; мы автоматически получим место в памяти, в которое будет по умолчанию записан 0.

Но большая часть данных хранится в экземплярах классов, память для которых выделяется при использовании ключевого слова new. По большому счету это тоже происходит автоматически, а после завершения использования обьекта память высвобождается сборщиком мусора. Но такие переменные являются ссылочными типами данных и ведут себя иначе. В них хранятся не сами данные, а ссылка на область в памяти с этими данными. Если в одну переменную записать значение другой переменной, то они обе будут указывать на одно и то же значение. Вот код, наглядно демонстрирующий эту разницу

string surname1 = "Пушкин ";

string surname2 = "Гончарова";

// в surname1 записывается значение surname2 но сами переменный продолжают существовать независимо

surname1 = surname2;

surname2 = "ААА";

Console.WriteLine("Значение surname1: " + surname1); // Гончарова

Console.WriteLine("Значение surname2: " + surname2); // ААА

Person person1 = new Person("Пушкин", "Александр", "Сергеевич");

Person person2 = new Person("Гончарова", "Наталья", "Николаевна");

// в person1 записывается ссылка на обьект person2 теперь обе переменные ссылаются на один и тот же обьект класса Person

person1 = person2;

person2.Surname = "AAA";

Console.WriteLine("Значение person1.Surname: " + person1.Surname); // ААА

Console.WriteLine("Значение person2.Surname: " + person2.Surname); // ААА

Console.ReadLine();

Отличие структур от классов без функций в том, что данные структуры копируются из одной в другую при записи одной переменной в другую, а при записи одной ссылочной переменной в другую копируется только ссылка на данные, что при большом объеме данных может работать намного быстрей.

С другой стороны, чтобы реально скопировать данные из одного объекта ссылочной типа в другой (и в итоге получить два разных объекта с одинаковыми данными, а не две ссылки на один и тот же) придется писать специальный код.

Когда именно какой-то объект становится ненужным и попадает под внимание сборщика мусора? На самом деле особенности работы сборщика мусора относятся к достаточно продвинутым и глубоким вопросам, так как это очень умная машина. Но как минимум одно связанное с этим понятие надо знать любому программисту - область видимости переменных. В большинстве случаев мы потеряем контроль над переменной после того, как она выйдет из этой области видимости - после этого она больше не будет доступна программисту и рано или поздно ее память будет освобождена сборщиком мусора. В большинстве случаев область видимости переменной ограничивается блоком кода, ограниченным двумя фигурными скобками. Если внутри такого блока есть еще один блок - то на него распространяется область видимости родительского блока. Пример сферической области видимости в вакууме

{

int testVariable = 1;

}

testVariable = 2; // такая программа просто не скомпиллируется, прямо в VisualStudio выдаст ошибку The name 'testVariable' does not exist in the current context

А вот так все будет в порядке.

int testVariable = 1;

{

testVariable = 2;

}

Другой вариант первой ошибки

int testVariable = 1;

{

int testVariable = 2;

}

А вот так все будет в порядке, поскольку переменные с одним и тем же именем объявляется в разных областях видимости одного и того же уровня, не зависящих друг от друга

{

int testVariable = 2;

Console.WriteLine(testVariable);

}

{

int testVariable = 2;

Console.WriteLine(testVariable);

}

Само собой в реальном программировании пустые блоки фигурных скобок не применяются, но все вышесказанное верно для всех тех случаев, когда они применяются осмысленно - логических условий, циклов, функций.

Наглядный пример более сложной задачи, при решении о которой необходимо помнить об особенностях работы сборщика мусора - использование Word для вывода данных в отчеты. В этом случае мы используем ресурс, неподвластный сборщику мусора - программу Word, запускаемую и управляемую из нашего кода. Если она становится не нужна, то ее надо закрывать вручную из кода - иначе на компьютере начнут плодится невидимые Word'ы в неограниченных количествах.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: