...
// Исследовать только объекты поколения 0.
GC.Collect(0);
GC.WaitForPendingFinalizers();
...
Кроме того, методу Collect() можно передать во втором параметре значение перечисления GCCollectionMode для точной настройки способа, которым исполняющая среда должна принудительно инициировать сборку мусора. Ниже показаны значения, определенные этим перечислением:
public enum GCCollectionMode
{
Default, // Текущим стандартным значением является Forced.
Forced, // Указывает исполняющей среде начать сборку мусора немедленно
Optimized // Позволяет исполняющей среде выяснить, оптимален
// ли текущий момент для удаления объектов.
}
Как и при любой сборке мусора, в результате вызова GC.Collect() уцелевшие объекты переводятся в более высокие поколения. Модифицируйте операторы верхнего уровня следующим образом:
Console.WriteLine("***** Fun with System.GC *****");
// Вывести оценочное количество байтов, выделенных в куче.
Console.WriteLine("Estimated bytes on heap: {0}",
GC.GetTotalMemory(false));
// Значения MaxGeneration начинаются c 0.
Console.WriteLine("This OS has {0} object generations.n",
(GC.MaxGeneration + 1));
Car refToMyCar = new Car("Zippy", 100);
Console.WriteLine(refToMyCar.ToString());
// Вывести поколение refToMyCar.
Console.WriteLine("nGeneration of refToMyCar is: {0}",
GC.GetGeneration(refToMyCar));
// Создать большое количество объектов для целей тестирования.
object[] tonsOfObjects = new object[50000];
for (int i = 0; i < 50000; i++)
{
tonsOfObjects[i] = new object();
}
// Выполнить сборку мусора только для объектов поколения 0.
Console.WriteLine("Force Garbage Collection");
GC.Collect(0, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
// Вывести поколение refToMyCar.
Console.WriteLine("Generation of refToMyCar is: {0}",
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
GC.GetGeneration(refToMyCar));
// Посмотреть, существует ли еще tonsOfObjects[9000].
if (tonsOfObjects[9000] != null)
{
Console.WriteLine("Generation of tonsOfObjects[9000] is: {0}",
GC.GetGeneration(tonsOfObjects[9000]));
}
else
{
Console.WriteLine("tonsOfObjects[9000] is no longer alive.");
// tonsOfObjects[9000] больше не существует
}
// Вывести количество проведенных сборок мусора для разных поколений.
Console.WriteLine("nGen 0 has been swept {0} times",
GC.CollectionCount(0)); // Количество сборок для поколения 0
Console.WriteLine("Gen 1 has been swept {0} times",
GC.CollectionCount(1)); // Количество сборок для поколения 1
Console.WriteLine("Gen 2 has been swept {0} times",
GC.CollectionCount(2)); // Количество сборок для поколения 2
Console.ReadLine();
Здесь в целях тестирования преднамеренно был создан большой массив типа object (состоящий из 50000 элементов). Ниже показан вывод программы:
***** Fun with System.GC *****
Estimated bytes on heap: 75760
This OS has 3 object generations.
Zippy is going 100 MPH
Generation of refToMyCar is: 0
Forcing Garbage Collection
Generation of refToMyCar is: 1
Generation of tonsOfObjects[9000] is: 1
Gen 0 has been swept 1 times
Gen 1 has been swept 0 times
Gen 2 has been swept 0 times
К настоящему моменту вы должны лучше понимать детали жизненного цикла объектов. В следующем разделе мы продолжим изучение процесса сборки мусора, обратившись к теме создания финализируемых объектов и освобождаемых объектов. Имейте в виду, что описываемые далее приемы обычно необходимы только при построении классов С#, которые поддерживают внутренние неуправляемые ресурсы.
Построение финализируемых объектов
В главе 6 вы узнали, что в самом главном базовом классе .NET Core, System.Object, определен виртуальный метод по имени Finalize(). В своей стандартной реализации он ничего не делает:
// System.Object