Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шпоры C#.doc
Скачиваний:
16
Добавлен:
22.09.2019
Размер:
472.58 Кб
Скачать

11. Типы значений и ссылочные типы. Динамическое использование памяти: стеки и кучи. Упаковка и распаковка.

Все типы в C# разделяются на две основные разновидности: структурные типы (value- based) или типы значений и ссылочные типы (reference- based). К структурным типам относятся все числовые типы данных (int, float и пр.), а также перечисления и структуры. При присвоении одного структурного типа другому присваивается не сам тип (как область в памяти), а его побитовая копия. Выполнение операций с использованием типов значений происходит быстрее, чем при использовании ссылочных типов. Память для структурных типов выделяется из стека.

int x=286;

у казатель

вершина стека

2 курс


2

8

6

дно стека

Стек резервируется для хранения данных, создаваемых во время компиляции программы. В стеке применяется принцип обслуживания типа LiFO (Last in First Out – последним применен- первым обслужен). Согласно этому методу, первым обрабатывается последний из поступивших запросов.

Выделение памяти.

Выделение памяти из кучи в среде Net Runtime происходит очень быстро. Система убеждается в том, что в управляемой куче хватает памяти для запрашиваемого объекта, возвращает указатель на эту память и переводит указатель на следующий после последнего объекта адрес.

Когда операционная система запускает приложение на выполнение, CLR резервирует непрерывный диапазон адресов адресного пространства, который называют управляемой кучей. Указатель NextPtr (Next Pointer) сохраняет адрес кучи, в который может быть размещён следующий объект. В начальный момент, когда в куче ещё нет ни одного объекта, этот указатель указывает на базовый адрес зарезервированного адресного пространства.

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

Объект С

Объект В

Объект А

У казатель NextPtr

Типы значений можно разделить на 3 группы: простые типы, структуры и перечисление.

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

stud1

stud2

неиспользованная Часть кучи

Ссылки (корни)

s tudent stud1= new student ();

s tudent stud2= new student ();

Ссылки указывают на местонахождение объектов в управляемой куче. Когда много создано объектов, пространство в управляемой куче может закончится. Тогда автоматически запускается сборщик мусора. Он отслеживает, есть ли в куче активные ссылки. Если ссылок на объект нет или объект установлен на null, то объект помечается для удаления.

При копировании ссылочного типа создаётся ещё одна ссылка, которая указывает на туже область оперативной памяти. Можно изменить исходный объект.

student stud3= stud1;

Обе переменные stud1 и stud3 ссылаются на один и тот же объект. На этот объект можно воздействовать, используя либо stud1, либо stud3.

stud3.Addstip (-10000);

stud3. Show_Student ( );

stud1. Show_Student ( ); (Получаем один и тоже знак)

От структурного типа к ссылочному типу и наоборот: упаковка и распаковка.

В C# предусмотрен очень простой механизм для преобразования структурного типа в ссылочный. Он получил название упаковки (boxing). Предположим, что у нас есть (создаём переменную S) short S=25;

А вот как выглядит процесс упаковки – преобразование объекта структурного типа в ссылочный: (Упаковываем переменную S) object objshort=s; (наше имя)

Упаковка- это процесс явного преобразования структурного типа в ссылочный. При этом происходит следующее: в управляемой куче создаётся новый объект и в него копируются внутренние данные старого объекта из стека (у нас-25).

Противоположная операция называется распаковкой (unboxing). Распаковка – это преобразование ссылки на объект в оперативной памяти обратно в структурный тип. Перед выполнением распаковки среда выполнения CLR производит проверку на совместимость между типом объекта в оперативной памяти и тем структурным типом, в который будет производиться распаковка.

(Обратная распаковка объекта)

short anotherShort=(short) obj’short;

Если же среда выполнения обнаружит, что происходит распаковка в неподходящий тип данных, будет сгенерировано исключение InvalidCastException.

(Неверная распаковка)

StringStr=(string)obj’short;

Когда нужно заниматься упаковкой и распаковкой?

Ответ – не слишком часто. В подавляющем большинстве случаев операции по упаковке и распаковке выполняются компилятором в C# полностью автоматически. Например, если структурный тип передаётся методу, который принимает в качестве параметра объект, упаковка произойдёт автоматически. Явная упаковка и распаковка используется в C# только тогда, когда это повысит производительность приложения.