I've spend my weekend trying to get my head around the finalizer in .net.
I was using the DisposableObject which exists in the Umbraco Core namespace. This class is meant as a base class (abstract) to be used by other classes. The class implements a very clean Dispose() pattern, and adds a virtual DisposeUnmanagedResources() method to clean up your unmanaged memory.
But... If you do not have unmanaged memory to clean, you better do not use the DisposableObject. This is because it is prepared to release unmanaged memory, it adds a Finalizer (the ~DisposableObject() method). And apparently adding a Finalizer to an object has an impact as it will live much longer than normally disposed objects.
Very interesting and thanks for the links and investigation!
Looks like we should create a DisposableObjectSlim or similar without a finalizer. This object originally came from v5 to implement a standard disposable pattern so it didn't need to be reimplemented over and over again.
Btw those IDisposable docs are 10000% better than they were in the last, afaik the DisposableObject implemented the 'best practices' according to MS docs at the time 😉
I was also convinced that the Finalizer had to be used when using IDisposable. It was due to a mem leak in another project I was reading the docs.
To be honest I don't know whether the DisposableObjectSlim is a good idea. The point of IDispose is to free unmanaged resources. If you want to wrap objects with a using() to be able to Dispose earlier, it might be a good thing.
One purpose of Dispose is to free unmanaged resources
Provides a mechanism for releasing unmanaged resources.
the other purpose is to follow the pattern when you need to clean things up when an object is out of scope or if you want to use the using syntax which is much nicer to do in many cases than to do a try/finally.
There's plenty of examples of objects that are IDisposable that are not dealing with unmanaged resources.
It is odd that even though we were calling GC.SuppressFinalize just having a finalizer still matters.
Stay away from Umbraco.Core.DisposableObject()
I've spend my weekend trying to get my head around the finalizer in .net.
I was using the
DisposableObject
which exists in the Umbraco Core namespace. This class is meant as a base class (abstract) to be used by other classes. The class implements a very clean Dispose() pattern, and adds a virtual DisposeUnmanagedResources() method to clean up your unmanaged memory.But... If you do not have unmanaged memory to clean, you better do not use the DisposableObject. This is because it is prepared to release unmanaged memory, it adds a Finalizer (the
~DisposableObject()
method). And apparently adding a Finalizer to an object has an impact as it will live much longer than normally disposed objects.Today, I learned the hard way. You should avoid messing around and trying to be smarter that the GC. From the Dispose design guidelines: avoid making types finalizable and carefully consider any case in which you think a finalizer is needed.
Lesson learned: stay away from DisposableObject() if you do not have unmanaged memory to release.
Very interesting and thanks for the links and investigation!
Looks like we should create a DisposableObjectSlim or similar without a finalizer. This object originally came from v5 to implement a standard disposable pattern so it didn't need to be reimplemented over and over again.
Btw those IDisposable docs are 10000% better than they were in the last, afaik the DisposableObject implemented the 'best practices' according to MS docs at the time 😉
I was also convinced that the Finalizer had to be used when using IDisposable. It was due to a mem leak in another project I was reading the docs.
To be honest I don't know whether the DisposableObjectSlim is a good idea. The point of IDispose is to free unmanaged resources. If you want to wrap objects with a
using()
to be able to Dispose earlier, it might be a good thing.One purpose of Dispose is to free unmanaged resources
the other purpose is to follow the pattern when you need to clean things up when an object is out of scope or if you want to use the
using
syntax which is much nicer to do in many cases than to do a try/finally.There's plenty of examples of objects that are IDisposable that are not dealing with unmanaged resources.
It is odd that even though we were calling
GC.SuppressFinalize
just having a finalizer still matters.True. I guess it's easier to see if there is a Finalizer that to check if the GC.SuppressFinalize() was called.
Just saw this has converted into an issue on the issue tracker: http://issues.umbraco.org/issue/U4-10815
is working on a reply...