Действительно ли безопасно получить доступ к членской переменной ссылочного типа в финализаторе?

Другими словами,

class Foo
{
    object obj;
    Foo() { obj = new object(); }
    ~Foo() { obj.ToString(); /* NullReferenceException? */ }
}
9
задан CannibalSmith 24 February 2010 в 15:53
поделиться

4 ответа

Это небезопасно, поскольку объект obj, возможно, уже был обработан сборщиком мусора. Также обратите внимание, что сборщик мусора не установит для ссылки значение null. Так что даже проверка на obj! = Null вам не поможет.

Подробнее см. Здесь: http://msdn.microsoft.com/en-us/magazine/cc163392.aspx#S3

" Обобщая этот принцип в Метод Dispose безопасно очищать все ресурсы, которые удерживает объект, независимо от того, являются ли они управляемыми объектами или собственными ресурсами. Однако в финализаторе безопасно очищать только объекты, которые не финализируются, и, как правило, финализатор следует только освобождать собственные ресурсы. "(Ваш объект может быть финализирован, поэтому вы не должны трогать его в другом финализаторе)

Это также причина того, почему у вас есть

if (удаление) {... }

в шаблоне IDisposable (см. Рисунок 2 по ссылке выше).

7
ответ дан 4 December 2019 в 11:41
поделиться

В общем, вы не хотите реализовывать финализаторы для своих объектов. Если вам нужно выполнить очистку ресурсов управляемых объектов, вы хотите сделать это в Dispose и правильно реализовать шаблон Dispose.

Если вы все-таки реализуете финализатор, вы хотите получить доступ только к неуправляемым ресурсам.

1
ответ дан 4 December 2019 в 11:41
поделиться

Если это вызывает беспокойство, то, вероятно, лучше избавиться, чем завершить .

0
ответ дан 4 December 2019 в 11:41
поделиться

Из 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 для очистки неуправляемых ресурсов

7
ответ дан 4 December 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: