Другими словами,
class Foo
{
object obj;
Foo() { obj = new object(); }
~Foo() { obj.ToString(); /* NullReferenceException? */ }
}
Это небезопасно, поскольку объект obj, возможно, уже был обработан сборщиком мусора. Также обратите внимание, что сборщик мусора не установит для ссылки значение null. Так что даже проверка на obj! = Null вам не поможет.
Подробнее см. Здесь: http://msdn.microsoft.com/en-us/magazine/cc163392.aspx#S3
" Обобщая этот принцип в Метод Dispose безопасно очищать все ресурсы, которые удерживает объект, независимо от того, являются ли они управляемыми объектами или собственными ресурсами. Однако в финализаторе безопасно очищать только объекты, которые не финализируются, и, как правило, финализатор следует только освобождать собственные ресурсы. "(Ваш объект может быть финализирован, поэтому вы не должны трогать его в другом финализаторе)
Это также причина того, почему у вас есть
if (удаление) {... }
в шаблоне IDisposable (см. Рисунок 2 по ссылке выше).
В общем, вы не хотите реализовывать финализаторы для своих объектов. Если вам нужно выполнить очистку ресурсов управляемых объектов, вы хотите сделать это в Dispose
и правильно реализовать шаблон Dispose.
Если вы все-таки реализуете финализатор, вы хотите получить доступ только к неуправляемым ресурсам.
Если это вызывает беспокойство, то, вероятно, лучше избавиться, чем завершить .
Из Object.Finalize :
Не гарантируется, что финализаторы двух объектов будут запускаться в каком-либо определенном порядке, даже если один объект относится к другому. То есть, если объект A имеет ссылку на объект B и оба имеют финализаторы, объект B мог уже быть завершен при запуске финализатора объекта A.
Короче говоря, вы не можете делать никаких предположений о состоянии ссылочных объектов во время финализатора.
Практически во всех случаях логика, реализованная в финализаторе, принадлежит шаблону Disposable. Это пример того, как правильно реализовать шаблон в .NET с помощью интерфейса IDisposable .
public class MyClass : IDisposable
{
private bool _disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if(disposing)
{
// Release unmanaged resources.
}
// Release managed resources (Streams, SqlConnections, etc.)
}
_disposed = true;
}
}
В том маловероятном случае, если вы работаете с неуправляемыми ресурсами, ознакомьтесь с этой статьей, чтобы узнать, как реализовать IDisposable
с финализатором:
MDSN: реализация Finalize и Dispose для очистки неуправляемых ресурсов