
- •С# и объектно-ориентированное программирование. Содержание
- •Разбор простой программы на с#.
- •Варианты метода Main ()
- •Формальное определение класса в с#
- •2.1Ссылки на самого себя
- •Построение цепочки вызовов конструкторов с использованием this.
- •Модификаторы доступа с#
- •Средства инкапсуляции с#
- •Инкапсуляция с использованием традиционных методов доступа и изменения
- •Инкапсуляция с использованием свойств .Net
- •Свойства, доступные только для чтения и только для записи
- •Статические свойства
- •Статические конструкторы
- •Наследование в с#
- •Работа с конструктором базового класса
- •Множественное наследование.
- •Ключевое слово sealed
- •Поддержка полиморфизма в с#
- •Ключевые слова virtual и override
- •Абстрактные классы
- •Полиморфный интерфейс
- •Сокрытие методов
- •Правила приведения к базовому и производному классу
- •Ключевое слово as
- •Ключевое слово is
- •Применение модели включения – делегирования.
- •Определение вложенных типов
- •Обработка исключений
- •Роль обработки исключений в .Net
- •Составляющие процесса обработки исключений в .Net
- •Генерация общего исключения
- •Перехват исключений
- •Создание специальных исключений, способ первый
- •Обработка нескольких исключений.
- •Блок finally
- •Замечания по работе с исключениями
- •Время жизни объектов
- •Базовые сведения о времени жизни объектов
- •Роль корневых элементов приложения
- •Поколения объектов
- •Параллельная сборка мусора в версиях .Net 1.0 - .Net 3.5
- •Фоновая сборка мусора в версии .Net 4.0
- •Создание финализируемых объектов
- •Описание процесса финализации
- •Создание высвобождаемых объектов
- •Повторное использование ключевого слова using в с#
- •Взаимодействие со сборщиком мусора
- •Принудительная активизация сборки мусора
- •Создание финализируемых и высвобождаемых типов
- •Формализованный шаблон очистки
Базовые сведения о времени жизни объектов
"Золотое правило" по управлению памятью в .NET звучит просто:
Правило. После создания, объект будет автоматически удален сборщиком мусора тогда, когда в нем отпадет необходимость. То есть, сборщик мусора удаляет объект из кучи тогда, когда тот становится недостижимым ни в одной части программного кода.
Например:
В этом простом примере, ссылка на объект Car (refToMyCar) была создана непосредственно внутри метода Main() и не передавалась за пределы определяющей области действия (ни в виде возвращаемого значения, ни в виде параметров). Поэтому после завершения вызова данного метода ссылка refToMyCar окажется недостижимой, а объект Саг, соответственно — кандидатом на удаление сборщиком мусора. Следует, однако, понять, что иметь полную уверенность в немедленном удалении этого объекта из памяти сразу же после выполнения метода Main() нельзя. Все, что в данный момент можно предполагать, так это то, что когда в CLR-среде будет в следующий раз производиться сборка мусора, объект refToMyCar может подпасть под процесс уничтожения.
Программирование в среде с автоматической сборкой мусора значительно облегчает разработку приложений. Программистам на C++ хорошо известно, что если они специально не позаботятся об удалении размещаемых в куче объектов, вскоре обязательно начнут возникать "утечки памяти". На самом деле отслеживание проблем, связанных с утечкой памяти, является одним из самых длительных (и утомительных) аспектов программирования в неуправляемых средах. Благодаря назначению ответственным за уничтожение объектов сборщика мусора, обязанности по управлению памятью, по сути, сняты с плеч программиста и возложены на CLR-среду.
CIL-код, генерируемый для ключевого слова new
При обнаружении ключевого слова new компилятор С# вставляет в реализацию метода CIL-инструкцию newobj. Если скомпилировать текущий пример кода и заглянуть в полученную сборку с помощью утилиты ildasm.exe, то можно обнаружить внутри метода Main() следующие CIL-операторы:
Рассмотрим роль CIL-инструкции newobj.
Дна начала важно понять, что управляемая куча представляет собой нечто большее, чем просто случайный фрагмент памяти, к которому CLR получает доступ. Сборщик мусора .NET "убирает" кучу довольно тщательно, причем (при необходимости) даже сжимает пустые блоки памяти с целью оптимизации. Чтобы ему было легче это делать, в управляемой куче поддерживается указатель (обычно называемый указателем на следующий объект или указателем на новый объект), который показывает, где точно будет размещаться следующий объект.
Таким образом, инструкция newobj заставляет CLR-среду выполнить перечисленные ниже ключевые операции.
Вычислить, сколько всего памяти требуется для размещения объекта (в том числе памяти, необходимой для членов данных и базовых классов).
Проверить, действительно ли в управляемой куче хватает места для обслуживания размещаемого объекта. Если хватает, вызвать указанный конструктор и вернуть вызывающему коду ссылку на новый объект в памяти, адрес которого совпадает с последней позицией указателя на следующий объект.
И, наконец, перед возвратом ссылки вызывающему коду переместить указатель на следующий объект, чтобы он указывал на следующую доступную позицию в управляемой куче. Весь описанный процесс схематично изображен на рис. 2.
Рис. 2. Детали размещения объектов в управляемой куче
Из-за постоянного размещения объектов приложением пространство в управляемой куче может со временем заполниться. В случае если при обработке следующей инструкции newobj среда CLR обнаруживает, что в управляемой куче не хватает пространства для размещения запрашиваемого типа, она приступает к сборке мусора и тем самым пытается освободить хоть сколько-то памяти. Поэтому следующее правило, касающееся сборки мусора, тоже звучит довольно просто.
Правило. В случае нехватки в управляемой куче пространства для размещения запрашиваемого объекта начинает выполняться сборка мусора.
Однако то, каким именно образом начнет выполняться сборка мусора, зависит от версии .NET, под управлением которой функционирует приложение.
На заметку! Когда объектные ссылки устанавливаются в null, компилятор С# генерирует CIL-код, который заботится о том, чтобы ссылка больше не ссылалась ни на какой объект. Установка ссылки в null не вынуждает сборщик мусора удалить объект из кучи, а просто позволяет явно разорвать связь между ссылкой и объектом, на который она ранее указывала.