После того как класс определен, в памяти можно размещать любое количество его объектов, применяя ключевое слово new языка С#. Однако следует иметь в виду, что ключевое слово new возвращает ссылку на объект в куче, а не действительный объект. Если ссылочная переменная объявляется как локальная переменная в области действия метода, то она сохраняется в стеке для дальнейшего использования внутри приложения. Для доступа к членам объекта в отношении сохраненной ссылки необходимо применять операцию точки С#:

using System;

using SimpleGC;

Console.WriteLine("***** GC Basics *****");

// Создать новый объект Car в управляемой куче.

// Возвращается ссылка на этот объект (refToMyCar).

Car refToMyCar = new Car("Zippy", 50);

// Операция точки (.) используется для обращения к членам

// объекта с применением ссылочной переменной.

Console.WriteLine(refToMyCar.ToString());

Console.ReadLine();

На заметку! Вспомните из главы 4, что структуры являются типами значений, которые всегда размещаются прямо в стеке и никогда не попадают в управляемую кучу .NET Core. Размещение в куче происходит только при создании экземпляров классов.

<p id="AutBody_Root350">Базовые сведения о времени жизни объектов</p>

При создании приложений C# корректно допускать, что исполняющая среда .NET Core позаботится об управляемой куче без вашего прямого вмешательства. В действительности "золотое правило" по управлению памятью в .NET Core выглядит простым.

Правило. Используя ключевое слово new, поместите экземпляр класса в управляемую кучу и забудьте о нем.

После создания объект будет автоматически удален сборщиком мусора, когда необходимость в нем отпадет. Конечно, возникает вполне закономерный вопрос о том, каким образом сборщик мусора выясняет, что объект больше не нужен? Краткий (т.е. неполный) ответ можно сформулировать так: сборщик мусора удаляет объект из кучи, только когда он становится недостижимым для любой части кодовой базы. Добавьте в класс Program метод, который размещает в памяти локальный объект Car:

static void MakeACar()

{

  // Если myCar - единственная ссылка на объект Car, то после

  // завершения этого метода объект Car *может* быть уничтожен.

  Car myCar = new Car();

}

Обратите внимание, что ссылка на объект Car(myCar) была создана непосредственно внутри метода MakeACar() и не передавалась за пределы определяющей области видимости (через возвращаемое значение или параметр ref/out). Таким образом, после завершения данного метода ссылка myCar оказывается недостижимой, и объект Car теперь является кандидатом на удаление сборщиком мусора. Тем не менее, важно понимать, что восстановление занимаемой этим объектом памяти немедленно после завершения метода MakeACar() гарантировать нельзя. В данный момент можно предполагать лишь то, что когда исполняющая среда инициирует следующую сборку мусора, объект myCar может быть безопасно уничтожен.

Как вы наверняка сочтете, программирование в среде со сборкой мусора значительно облегчает разработку приложений. И напротив, программистам на языке C++ хорошо известно, что если они не позаботятся о ручном удалении размещенных в куче объектов, тогда утечки памяти не заставят себя долго ждать. На самом деле отслеживание утечек памяти — один из требующих самых больших затрат времени (и утомительных) аспектов программирования в неуправляемых средах. За счет того, что сборщику мусора разрешено взять на себя заботу об уничтожении объектов, обязанности по управлению памятью перекладываются с программистов на исполняющую среду.

<p id="AutBody_Root351">Код CIL для ключевого слова new</p>

Когда компилятор C# сталкивается с ключевым словом new, он вставляет в реализацию метода инструкцию newobj языка CIL. Если вы скомпилируете текущий пример кода и заглянете в полученную сборку с помощью утилиты ildasm.ехе, то найдете внутри метода MakeACar() следующие операторы CIL:

.method assembly hidebysig static

          void  '<

$>g__MakeACar|0_0'() cil managed

{

    // Code size       8 (0x8)

    .maxstack  1

    .locals init (class SimpleGC.Car V_0)

    IL_0000: nop

    IL_0001: newobj     instance void SimpleGC.Car::.ctor()

    IL_0006: stloc.0

    IL_0007: ret

Перейти на страницу:

Похожие книги