Console.WriteLine("then force the GC to invoke Finalize()");
// Нажмите клавишу
// и затем заставить сборщик мусора вызвать метод Finalize()
// В зависимости от мощности вашей системы
// вам может понадобиться увеличить эти значения.
CreateObjects(1_000_000);
// Искусственно увеличить уровень давления.
GC.AddMemoryPressure(2147483647);
GC.Collect(0, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.ReadLine();
static void CreateObjects(int count)
{
MyResourceWrapper[] tonsOfObjects =
new MyResourceWrapper[count];
for (int i = 0; i < count; i++)
{
tonsOfObjects[i] = new MyResourceWrapper();
}
tonsOfObjects = null;
}
На заметку! Единственный способ гарантировать, что такое небольшое консольное приложение принудительно запустит сборку мусора в .NET Core, предусматривает создание огромного количества объектов в памяти и затем установит ссылку на них в null. После запуска этого приложения не забудьте нажать комбинацию клавиш
Подробности процесса финализации
Важно всегда помнить о том, что роль метода Finalize() состоит в обеспечении того, что объект .NET Core сумеет освободить неуправляемые ресурсы, когда он подвергается сборке мусора. Таким образом, если вы строите класс, в котором неуправляемая память не применяется (общепризнанно самый распространенный случай), то финализация принесет мало пользы. На самом деле по возможности вы должны проектировать свои типы так, чтобы избегать в них поддержки метода Finalize() по той простой причине, что финализация занимает время.
При размещении объекта в управляемой куче исполняющая среда автоматически определяет, поддерживает ли он специальный метод Finalize(). Если да, тогда объект помечается как
Когда сборщик мусора решает, что наступило время высвободить объект из памяти, он просматривает каждую запись в очереди финализации и копирует объект из кучи в еще одну управляемую структуру под названием таблица Finalize() на каждом объекте из упомянутой таблицы
Подводя итоги, следует отметить, что хотя финализация объекта гарантирует ему возможность освобождения неуправляемых ресурсов, она все равно остается недетерминированной по своей природе, а из-за незаметной дополнительной обработки протекает значительно медленнее.
Построение освобождаемых объектов
Как вы уже видели, финализаторы могут использоваться для освобождения неуправляемых ресурсов при запуске сборщика мусора. Тем не менее, учитывая тот факт, что многие неуправляемые объекты являются "ценными элементами" (вроде низкоуровневых дескрипторов для файлов или подключений к базам данных), зачастую полезно их освобождать как можно раньше, не дожидаясь наступления сборки мусора. В качестве альтернативы переопределению метода Finalize() класс может реализовать интерфейс IDisposable, в котором определен единственный метод по имени Dispose():
public interface IDisposable
{
void Dispose();
}
При реализации интерфейса IDisposable предполагается, что когда Dispose() перед тем, как позволить объектной ссылке покинуть область действия. Таким способом объект может производить любую необходимую очистку неуправляемых ресурсов без помещения в очередь финализации и ожидания, пока сборщик мусора запустит логику финализации класса.