Объясните, пожалуйста, почему при выполнении данного кода не будет выполнен финализатор?
using System;
namespace Where_Destructor
{
class Foo : IDisposable
{
public String s;
public Foo()
{
Console.WriteLine("I am constructed");
}
public void Dispose()
{
Console.WriteLine("I am disposed");
}
~Foo()
{
Console.WriteLine("I am destructed");
}
}
class Program
{
static void Main(string[] args)
{
Foo f;
using (f = new Foo())
{
}
f = null;
GC.Collect();
Console.ReadKey();
}
}
}
Результатом будет:
I am constructed I am disposed
Однако, если мы изменим код на такой:
using System;
namespace Where_Destructor
{
class Foo : IDisposable
{
public String s;
public Foo()
{
Console.WriteLine("I am constructed");
}
public void Dispose()
{
Console.WriteLine("I am disposed");
}
~Foo()
{
Console.WriteLine("I am destructed");
}
}
class Program
{
static void Main(string[] args)
{
Foo f = new Foo())
f = null;
GC.Collect();
Console.ReadKey();
}
}
}
то финализатор вызывается вполне успешно.
Результат:
I am constructed I am destructed
Финализатор в первом варианте не вызывается по нескольким причинам:
Финализатор не обязательно отрабатывает в момент сборки мусора. Даже наоборот, объект с финализатором продолжит жить после сборки мусора, ради того, чтобы системный поток смог вызвать на нем финализатор.
Вы проверяете ваш код в Debug сборке. В Debug время жизни локальных переменных может продлеваться ради удобства отладки. Дебаггер вполне мог пометить первое значение f как живущее до конца метода.
Если хотите получить гарантированный вызов финализатора - допишите ручное ожидание и проверяйте в Release:
static void Main(string[] args)
{
Foo f;
using (f = new Foo())
{
}
f = null;
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadKey();
}
Проверил ваш код на двух версиях фреймворка: 4.7 и 4.0.
Проверил в режимах Debug и Release. Итого 4 варинта.
На обеих версиях фреймворка поведение одинаковое. Оно зависит от дебага/релиза.
В Debug "I am destructed" не выводится (вернее, выводится уже после нажатия на клавишу, после Console.ReadKey
).
В Release "I am destructed" выводится сразу.
Вывод: цитата PashaPash
В Debug время жизни локальных переменных может продлеваться ради удобства отладки.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Один мой друг спрашивает, возможна ли такая ситуация в C# когда в куче будет храниться адрес объекта (ссылка на объект) в стеке? С учетом того...
Я пытаюсь сделать протектор для программ на C#Суть его в том, что защищаемый файл переводится в байты и шифруется
У меня при компиляции сборки в Release появляется вот такая ошибка: