C# не является C ++. Деструкторы, или, вернее, финализаторы, являются функцией для очень специфических c целей, а именно для обработки удаления неуправляемых ресурсов, содержащихся в ваших объектах. Наполнение лога программы c в финализаторах - одна из немногих очень плохих идей, которые вы можете иметь с C#. Почему? Вот краткое изложение:
- Нет гарантии, когда объект будет собран, когда он выходит из области видимости.
- Черт, нет гарантии, что коллекция когда-либо произойдет, если нет никакого давления памяти.
- Нет никакой гарантии относительно порядка, в котором запускается финализатор объекта.
- Нет никакой гарантии относительно того, когда запускается финализатор объекта - может быть сразу после того, как он выходит из области видимости, может через минуту.
- Черт, нет гарантии, что финализатор когда-либо запустится.
- Нет гарантии, что, если он запустится, он запустится после того, как завершится ваш ctor. Таким образом, в вашем случае вы можете уменьшить число экземпляров, не увеличивая его. Конечно, это вряд ли произойдет, но это может произойти.
- О, это также отрицательно влияет на производительность всего вашего приложения, но это довольно незначительно по сравнению со злом выше.
Обычно при использовании финализаторов все, что вы знаете, неверно . Финализаторы настолько злы, что есть часть вторая этого!
Принцип использования финализаторов - не . Даже если вы опытный C# разработчик, шансы на то, что вам на самом деле нужен финализатор, очень малы, в то время как шансы на то, что вы получите что-то не так при написании этого, огромны . Если вы вынуждены работать с неуправляемыми ресурсами, следуйте рекомендациям и используйте SafeHandle
.
Если вам требуется подсчитать количество экземпляров, лучше всего использовать IDisposable
шаблон . Это совместный способ сделать это, означающий, что вызывающий код должен будет на самом деле Dispose()
вашего объекта для уменьшения числа. Но это не может быть по-другому. Суть в том, что в C# нет надежного способа что-то сделать, когда последняя ссылка на объект выходит из области видимости .
ОБНОВЛЕНИЕ:
Я надеюсь, что я отговорил вас от написания финализаторов. Серьезно, если вы не профессионал и точно не знаете, что вам нужен финализатор и можете описать все, что происходит на уровне CLR, просто не делайте этого. Однако . Есть отвратительный взлом, который вы можете использовать, чтобы получить то, что вы хотите. Эти два заклинания:
GC.Collect();
GC.WaitForPendingFinalizers();
должны заставить коллекцию произойти, которая поместит ваши объекты в очередь финализатора и подождет, пока все они завершатся sh. Если вы выполняете это после каждого теста, это должно дать вам ожидаемое поведение. Но, пожалуйста, ради нас всех, не используйте это в серьезном коде. Я только что показал вам ужасно острый обоюдоострый клинок. Без какой-либо ручки. Это в огне. Этот второй метод даже не гарантированно завершится.