Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
My_shpory_Ivan_Ivanich (2).docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
149.35 Кб
Скачать

2. Жизненный цикл объектов

В С# общий принцип управления памятью формулируется очень просто: для создания объекта в области «управляемой кучи» (managed heap) используется ключевое слово new. Среда выполнения .NET автоматически удалит объект тогда, когда он больше не будет нужен. Правило в целом вполне понятно, однако возникает один дополнительный вопрос: а как среда выполнения определяет, что объект больше не нужен? Короткий (то есть неполный) ответ гласит, что среда выполнения удаляет объект из памяти, когда в текущей области видимости больше не остается активных ссылок на этот объект.

Вне зависимости от того, насколько осторожно вы будете создавать объекты, как только место в управляемой куче заканчивается, автоматически запускается сборщик мусора (garbage collector, GC). 

Декструктор/ Finalize

class Car

{

~Car() // destructor

{

// cleanup statements...

}

}

Деструктор неявным образом вызывает метод Finalize для базового класса объекта. Следовательно, предыдущий код деструктора неявным образом преобразуется в следующий код:

protected override void Finalize()

{

try

{

// Cleanup statements...

}

finally

{

base.Finalize();

}

}

Это означает, что метод Finalize вызывается рекурсивно для всех экземпляров цепочки наследования начиная с самого дальнего и заканчивая самым первым.

Высвобождение ресурсов явным образом

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

Сборщик мусора

Вопрос №1

3. Неуправляемый код и указатели

Для обеспечения строгой типизации и безопасности C# по умолчанию не поддерживает арифметические операции над указателями. Однако с помощью ключевого слова unsafe можно определить небезопасный контекст для использования указателей.

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

Небезопасный код имеет следующие свойства.

  • Методы, типы и блоки кода могут определяться как небезопасные.

  • В некоторых случаях небезопасный код может повысить производительность приложения за счет удаления проверок границ массива.

  • Использование небезопасного кода необходимо при вызове встроенных функций, требующих указателей.

  • Использование небезопасного кода создает угрозу безопасности и стабильной работы.

  • Для компиляции небезопасного кода в C# необходимо, чтобы приложение было скомпилировано с помощью /unsafe.

Указатели.

В небезопасном контексте тип может быть типом указателя, типом значения или ссылочным типом. Объявления типа указателя выполняется одним из следующих способов:

{type}* identifier;

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

int a = 10;

// Должно быть в небезопасном коде, чтобы использовать внутренние указатели.

unsafe

{

fixed (int* p = &a)

{

int* p2 = p;

Console.WriteLine(*p2);

}

}

Оператор fixed не позволяет сборщику мусора переносить перемещаемую переменную. Оператор fixed допускается только в небезопасном контексте. Оператор fixed задает указатель на управляемую переменную и "закрепляет" эту переменную во время выполнения оператора. Без fixed, указатели на перемещаемые управляемые переменные были бы мало полезны, так как при сборке мусора переменные переносились бы непредсказуемым образом. Компилятор C# позволяет назначить указатель только управляемой переменной в операторе fixed.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]