开发者

GarbageCollector nullifying member fields?

开发者 https://www.devze.com 2023-04-06 11:52 出处:网络
I am debugging some C# class (let\'s say, Foo) which has a Dispose-Finalize pattern implemented, i.e. its Finalizer is calling Dispose() in case if Dispose has not already been called.

I am debugging some C# class (let's say, Foo) which has a Dispose-Finalize pattern implemented, i.e. its Finalizer is calling Dispose() in case if Dispose has not already been called.

Within the Dispose() there is logging code which accesses some member of Foo (let's say Bar). Bar is also an instance of some reference type, is readonly (created in the Foo's constructor) and is not exposed anywhere outside of Foo. So, at the time of Foo's garbage collection Bar is likely to be already collected as well. The theory says that such member fields should not be accessed from the Finalize thread.

But the logging code was not aware of theory and tryed to log some of the Bar's properties. And the process crashed with NullReferenceException in the Finalizer's thread.

I understand that bad things may happen when you ignore the theory, but I 开发者_运维技巧was not expected NRE: does the Garbage Collector srts the references to collected objects to null? Or am I missing something else?


In Implementing a Dispose Method, they specifically caution about accessing other objects from the finalizer. That's why they have the pattern:

~MyObject()
{
    Dispose(false);  // False because it's being called in a finalizer
}

public void Dispose()
{
    Dispose(true);  // True because it was called from user code
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        // here it's safe to access other CLR objects
    }

    // Here you dispose of any unmanaged objects
}

If you depart from this pattern--especially if the finalizer calls Dispose and tries to access other objects that might already have been disposed, you're going to have problems.

Note also that you don't need a finalizer unless you're creating a class that allocates unmanaged resources. If your class is only using CLR objects or third party libraries that provide .NET objects, then there's no need for the finalizer.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号