IDisposable pattern is expensive to implement. I've counted 17 lines of code before even starting to actually dispose resources.
Eric Lippert recently wrote a blog post bringing up an interesting point: any time a finalizer runs, it is a bug. I think it make perfect sense. If the IDisposable pattern is always followed, Finalizer should always be suppressed. It will never have a chance to run. If we accept that finalizer run is a bug, then does it make sense to have a guideline to force developers to derive from the following abstract class and forbid directly implementing the IDisposable interface.
public abstract class AbstractDisaposableBase: IDisposable
{
~AbstractDisaposableBase()
{
ReportObjectLeak();
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected abstract void Dispose(bool disposing);
[Conditional("DEBUG")]
private void ReportObjectLeak()
{
//Debug.Assert(false, "leaked instance");
//throw new Exception("leaked instance");
}
}
The benefits are clear:
Implementing dispose becomes easy and error free like below:
class MyClass1 : DisablableBase
{
protected override void Dispose(bool disposing)
{
//dispose both managed and unmamaged resources as though disposing==true
}
}
Not disposed object got reported
Disposable pattern is always followed
But, is there any problem with such a guideline?
One possible problem is that all disposable object will have a finalizer defined. But since the finalizer is always suppressed, there should not be any performance penalties.
What are your thoughts?
does it make sense to have a guideline to force developers to derive from the following abstract class
No, solely for the reason that C# doesn't have multiple inheritance. Interfaces describe behavior, inheritance dictates "is-a". You'll thoroughly limit the object-oriented design of your classes if you enforce this rule.
For example you can't introduce base classes for business objects that are not disposable, where a derived class would be.
But since the finalizer is always suppressed, there should not be any performance penalties.
Instances of the AbstractDisaposableBase subclasses will still be participating in the finalization queue management, so there will be a performance impact for this.
Related
Microsoft design guidelines mention Dispose pattern and scenarios how to use it:
DO implement the Basic Dispose Pattern on types containing instances
of disposable types. See the Basic Dispose Pattern section for details
on the basic pattern.
Later, they show the Basic Dispose Pattern as follows:
public class DisposableResourceHolder : IDisposable {
private SafeHandle resource; // handle to a resource
public DisposableResourceHolder(){
this.resource = ... // allocates the resource
}
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing){
if (disposing){
if (resource!= null) resource.Dispose();
}
}
}
My questions are:
Why do we need to implement Dispose(bool) if it has just a single call with parameter true? It could be easily simplified to just parameterless Dispose() {resource?.Dispose();}. Note we don't need finalizer here because objects we are referencing are managed and have their own finalizers, so they won't be leaked.
Why do they recommend to call GC.SuppressFinalize(this) while not having finalizer? GC anyway wouldn't call finalizer because it does not exist!
The only case when I see the need of Dispose(bool) is when we really have some unmanaged references, which does not implement IDisposable nor finalizer (like shown in this article). But then the meaning of bool disposing would be bool includingManagedResources. So why is it named so misleading 'disposing' to what it should do in fact?
Other classes could inherit from your class. Considering that the deriving class also holds unmanaged resources (recommended or not), this class should then add the finalizer calling Dispose(false). If your class was sealed I would agree with you.
Because the method void Dispose() should not be virtual following the guidelines from Microsoft and thus deriving classes would then have no chance to suppress finalization after disposal. Your implementation might not need a finalizer, but probably deriving classes do.
It's called disposing for no specific reason in my opinion. I personally would rename it as well.
Anyway, from my point of view it is not a good approach to mix owning managed and unmanaged resources. As already mentioned in the comment even Microsoft recommends to encapsulate unmanaged resources into managed ones thus the cases where you need to implement finalizers are probably rare. I cannot remember when I did this myself the last time.
I am also not sticking to the implementation from the guidelines for multiple reasons, like misleading naming or because it's hard to understand. An alternative approach would be this answer.
I know that Finalize method is used by garbage collector to let object free up unmanaged resources. And from what I know, Object.Finalize is never called directly by GC (object is added to f-reachable queue during it's construction if it's type overrides the Finalize method by implementing finalizer).
Object.Finalize is only called from autogenerated finalizer code:
try
{
//My class finalize implementation
}
finally
{
base.Finalize(); // Here chain of base calls will eventually reach Object.Finalize/
}
So having an arbitrary class, derived from Object, wouldn't call Object.Finalize - you need finalizer for Object.Finalize to make sense and for most classes it doesn't make sense and is unused (not saying it's implementation is empty in fact).
Would it be too complex to check existence of Finalize method in a class without it overriding Object.Finalize, and generating root finalizer without try{}finally{base.Finalize()} call? Something similar to Add method for collection initializing - you don't have to implement any interface or override that method - just implement public void Add(item) method.
It would complicate C# compiler a bit, but make finalizer run slightly faster by removing one redundant call, and most importantly - make Object class easier to understand without having protected Finalize method with empty implementation while it doesn't need to finalize anything.
Also it might be possible to implement FinalizableObject class, derived from Object and make compiler derive all classes which have finalizer from that. It could implement IDisposable and make the disposing pattern, recommended by Microsoft reusable without need to implement it in every class. Actually I'm surprised such base class doesn't exist.
Edit
The garbage collection does not call the child implementation of Object.Finalise unless the method is overridden. Why is it available to all objects? So that it can be overridden when needed but unless it is there is no performance impact. Looking at documentation here, it states;
The Object class provides no implementation for the Finalize method, and the garbage collector does not mark types derived from Object for finalization unless they override the Finalize method.
Notes on finalization
Quoting directly from Ben Watson's excellent book Writing High-Performance .NET Code as he explains far better than I ever could;
Never implement a finalizer unless it is required. Finalizers are code, triggered by the garbage collector to cleanup unmanaged resources. They are called from a single thread, one after the other, and only after the garbage collector declares the object dead after a collection. This means that if your class implements a finalizer, you are guaranteeing that it will stay in memory even after the collection that should have killed it. This decreases overall GC efficiency and ensures that your program will dedicate CPU resources to cleaning up your object.
If you do implement a finalizer, you must also implement the IDisposable
interface to enable explicit cleanup, and call GC.SuppressFinalize(this)
in the Dispose method to remove the object from the finalization queue.
As long as you call Dispose before the next collection, then it will clean up the object properly without the need for the finalizer to run. The following example correctly demonstrates this pattern;
class Foo : IDisposable
{
~Foo()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.managedResource.Dispose();
}
// Cleanup unmanaged resource
UnsafeClose(this.handle);
// If the base class is IDisposable object, make sure you call:
// base.Dispose();
}
}
Note Some people think that finalizers are guaranteed to run. This is generally true, but not absolutely so. If a program is force-terminated
then no more code runs and the process dies immediately. There is also a time limit to how long all of the finalizers are given on process shutdown. If your finalizer is at the end of the list, it may be skipped. Moreover,
because finalizers execute sequentially, if another finalizer has an infinite loop bug in it, then no finalizers after it will ever run. While finalizers are not run on a GC thread, they are triggered by a GC so if you have no collections, the finalizers will not run. Therefore, you should not rely on finalizers to clean up state external to your process.
Microsoft has a good write up on finalizers and the Disposable pattern here
The C# language destructor syntax obscures too much about what a finalizer really does. Perhaps best demonstrated with a sample program:
using System;
class Program {
static void Main(string[] args) {
var obj = new Example();
obj = null; // Avoid debugger extending its lifetime
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadLine();
}
}
class Base { ~Base() { Console.WriteLine("Base finalizer called"); } }
class Derived : Base { ~Derived() { Console.WriteLine("Derived finalizer called"); } }
class Example : Derived { }
Output:
Derived finalizer called
Base finalizer called
There are some noteworthy things about this behavior. The Example class itself does not have a finalizer, yet its base class finalizers are called anyway. That the Derived class finalizer is called before the Base class finalizer is not accidental. And note that the Derived class' finalizer has no call to base.Finalize(), even though the MSDN article for Object.Finalize() demands that it does, yet it is called anyway.
You may easily recognize this behavior, it is the way a virtual method behaves. One whose override calls the base method, like virtual method overrides commonly do. Which is otherwise exactly what it is inside the CLR, Finalize() is a plain virtual method like any other. The actual code generated by the C# compiler for the Derived class' destructor resembles this:
protected override Derived.Finalize() {
try {
Console.WriteLine("Derived finalizer called");
}
finally {
base.Finalize();
}
}
Not valid code, but the way it could be reverse-engineered from the MSIL. The C# syntax sugar ensures you can never forget to call the base finalizer and that it can't be aborted by a thread abort or AppDomain unload. The C# compiler does not otherwise help and auto-generate a finalizer for the Example class; the CLR does the necessary work of finding the finalizer of the most-derived class, traversing the method tables of the base classes until it finds one. And likewise helps in the class loader by setting a flag to indicate that Example has base classes with a finalizer so needs to be treated specially by the GC. The Base class finalizer calls Object.Finalize(), even though it doesn't do anything.
So key point is that Finalize() is actually a virtual method. It therefore needs a slot in the method table for Object so a derived class can override it. Whether it could have been done differently is pretty subjective. Certainly not easily and not without forcing every language implementation to special-case it.
There is a LOT of info around about the "standard full" IDisposable implementation for disposing of unmanaged resources - but in reality this case is (very) rare (most resources are already wrapped by managed classes). This question focuses on a mimimal implementation of IDisposable for the much more common "managed resources only" case.
1: Is the mimimal implementation of IDisposable in the code below correct, are there issues?
2: Is there any reason to add a full standard IDisposable implementation (Dispose(), Dispose(bool), Finalizer etc) over the minimal implimentation presented?
3: Is it OK/wise in this minimal case to make the Dispose virtual (since we are not providing Dispose(bool))?
4: If this minimal implementation is replaced with a full standard implementation that includes a (useless, in this case) finalizer - does this change how the GC handles the object? Are there any downsides?
5: The example includes Timer and event handlers as these cases are particularly important not to miss as failing to dispose them will keep objects alive and kicking (this in the case of Timer, eventSource in case of the event handler) until the GC gets round to disposing them in its time. Are there any other examples like these?
class A : IDisposable {
private Timer timer;
public A(MyEventSource eventSource) {
eventSource += Handler
}
private void Handler(object source, EventArgs args) { ... }
public virtual void Dispose() {
timer.Dispose();
if (eventSource != null)
eventSource -= Handler;
}
}
class B : A, IDisposable {
private TcpClient tpcClient;
public override void Dispose() {
(tcpClient as IDispose).Dispose();
base.Dispose();
}
}
refs:
MSDN
SO: When do I need to manage managed resources
SO: How to dispose managed resource in Dispose() method in C#
SO: Dispose() for cleaning up managed resources
The implementation is correct, there are no issues, provided no derived class directly owns an unmanaged resource.
One good reason to implement the full pattern is the "principle of least surprise". Since there is no authoritative document in MSDN describing this simpler pattern, maintenance developers down the line might have their doubts - even you felt the need to ask StackOverflow :)
Yes it's OK for Dispose to be virtual in this case.
The overhead of the unnecessary finalizer is negligible if Dispose has been called, and is correctly implemented (i.e. calls GC.SuppressFinalize)
The overwhelming majority of IDisposable classes outside the .NET Framework itself are IDisposable because they own managed IDisposable resources. It's rare for them to directly hold an unmanaged resource - this only happens when using P/Invoke to access unmanaged resources that aren't exposed by the .NET Framework.
Therefore there is probably a good argument for promoting this simpler pattern:
In the rare cases that unmanaged resources are used, they should be wrapped in a sealed IDisposable wrapper class that implements a finalizer (like SafeHandle). Because it's sealed, this class doesn't need the full IDisposable pattern.
In all other cases, the overwhelming majority, your simpler pattern could be used.
But unless and until Microsoft or some other authoritative source actively promotes it, I'll continue to use the full IDisposable pattern.
Another option is to refactor your code to avoid inheritance and make your IDisposable classes sealed. Then the simpler pattern is easy to justify, as the awkward gyrations to support possible inheritance are no longer necessary. Personally I take this approach most of the time; in the rare case where I want to make a non-sealed class disposable, I just follow the 'standard' pattern. One nice thing about cultivating this approach is that it tends to push you toward composition rather than inheritance, which generally makes code easier to maintain and test.
My recommended Dispose pattern is for a non-virtual Dispose implementation to chain to a virtual void Dispose(bool), preferably after something like:
int _disposed;
public bool Disposed { return _disposed != 0; }
void Dispose()
{
if (System.Threading.Interlocked.Exchange(ref _disposed, 1) != 0)
Dispose(true);
GC.SuppressFinalize(this); // In case our object holds references to *managed* resources
}
Using this approach will ensure that Dispose(bool) only gets called once, even if multiple threads try to invoke it simultaneously. Although such simultaneous disposal attempts are rare(*), it's cheap to guard against them; if the base class doesn't do something like the above, every derived class must have its own redundant double-dispose guard logic and likely a redundant flag as well.
(*) Some communications classes which are mostly single-threaded and use blocking I/O allow Dispose to be called from any threading context to cancel an I/O operation which is blocking its own thread [obviously Dispose can't be called on that thread, since that thread can't do anything while it's blocked]. It's entirely possible--and not unreasonable--for such objects, or objects which encapsulate them, to have an outside thread try to Dispose them as a means of aborting their current operation at just the moment they were going to be disposed by their main thread. Simultaneous Dispose calls are likely to be rare, but their possibility doesn't indicate any "design problem" provided that the Dispose code can act upon one call and ignore the other.
A lot of my classes repeat the below code to implement IDisposable. This seems to violate the DRY (Don't Repeat Yourself) principle. I could avoid some of the work by creating an AbstractDisposable base class, but that seems inappropriate / wouldn't work if I needed to extend other existing objects (assuming those objects weren't themselves disposable).
Another option would be to use a template/meta language where I could specify lists of managed and unmanaged resources for each class and have the generic Dispose Pattern auto generated when I build my project - but so far I've not played with meta languages / this seems extreme for such a common scenario.
public class SomeDisposableClass : IDisposable
{
IDisposable _something; //a managed resource (unique to this class / here for illustration)
/* ... loads of code unique to this class ... */
#region Dispose Pattern
private bool _disposed = false;
~SomeDisposableClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if (!this._disposed)
{
if (disposing)
{
// Dispose managed resources.
if (this._something!=null) this._something.Dispose(); //(unique to this class / here for illustration)
}
// Clean up any unmanaged resources
this._disposed = true;
}
}
#endregion
}
Is there a good way to implement a suitable Dispose pattern without violating the DRY principle?
I try to avoid IDisposable as best as I can. The problem is that it spreads throughout your code base. If a class has a disposable member, that class needs to implement IDisposable, too, etc.
Furthermore, IDisposable has problems when we are talking about type hierarchies.
A common scenario is to stick IDisposable onto a base class or even an interface if you think the derived classes need to free resources. However, most of the times, that's only an assumption and it really depends on the actual implementation if resource cleanup is needed or not, making the interface a leaky abstraction.
It would be better to only implement the interface if the class really needs it.
But this comes with its own problems:
How is the consumer of a certain interface supposed to know that the concrete instance he got - for example as a constructor parameter - needs to be disposed? He would have to explicitly check for it. And he would basically have to do this for every single instance of every non-sealed type he gets handed.
These are just two examples that show that you are best off to design your classes in a way so that they don't require the implementation of IDisposable.
However, if you really need to implement this interface, you should follow the Disposable Design Pattern as described by this CodeProject article.
It basically divides your types into two levels:
Level 0: Classes of level 0 contain only unmanaged resources, no managed ones. These classes need most of the usual default IDisposable pattern, although you don't have to implement the part that handles managed resources.
Level 1: Classes of level 1 contain only managed resources, both of Level 0 and 1. These classes only need a simplified implementation of IDisposable because they don't contain unmanaged resources. The implementation basically just calls Dispose on each of its Level 0 and Level 1 members and on its base class.
i don't think you are violating the DRY principle here. Because although you are disposing in each class but you are essentially not doing the same thing.,
I found this code in Mono reimplementation of cryptographic transforms.
I didn't modify or simplify anything - this is how it actually goes (there are comments like // Dispose unmanaged objects, but nothing is actually done).
Now - the IDisposable-related code seems redundant to me. Can this somehow be simplified / removed completely without breaking something important?
public class ToBase64Transform : ICryptoTransform
{
private bool disposed;
~ToBase64Transform()
{
Dispose(false);
}
public void Clear()
{
Dispose(true);
}
void IDisposable.Dispose()
{
Dispose(true);
// Finalization is now unnecessary.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed) return;
if (disposing)
{
}
disposed = true;
}
Full source is located here.
If it wraps unmanaged components, then that is the most appropriate implemntation.
If there aren't any unmanaged components, and it won't be subclassed, then yes; you can remove the finalizer and make it just have a simple Dispose():
public sealed class ToBase64Transform : ICryptoTransform
{
private bool disposed;
public void Dispose()
{
if (disposed) return;
// Dispose managed objects
disposed = true;
}
If there aren't any managed disposable components either, then ... just don't make it implement IDisposable.
I'm not sure I would expect a "Clear()" method to call "Dispose()", but maybe that is the norm in the context of crypto-streams.
A few points:
The public API that Mono expose must match the one provided by Microsoft or things will break. That includes finalizers (even when they are not needed by Mono). It's common for Mono to implement more stuff in managed code than Microsoft (actually very common in cryptography);
The type is not sealed so the Dispose(bool) method must be called (e.g. from the finalizer) nor abstract so the IDisposable interface must be implemented;
Mono comes with an extensive set of unit tests. When something looks weird it's a good idea to look at them. Matching MS implementation is not always straightforward and the MSDN documentation (while good and frequently updated) is not rarely enough or totally complete/right.
In this case the code inside Dispose(bool) is not required. I suspect it comes from a template (or from copy/pasting from another file) or the author was not sure if this code would move into unmanaged code in the future. Removing it is unlikely to change performance/size but fell free to submit a bug report (or pull request) to have it removed.
That's a completely standard way of implementing IDisposable. Agreed, no work is done, but if it has to be there for compatibility with MS.Net, then it's best done right.
A class which inherits from a base which implements IDisposable will generally need to ensure that a call to IDisposable.Dispose will call the base class' dispose logic as well as its own. This requires that at least one one of two conditions must apply:
There must be some means by which the derived class can ask to have derived-class Dispose logic called from the base class' implementation of IDisposable.Dispose(), without having to re-implement IDisposable.Dispose() itself.
If the derived class does re-implement IDisposable.Dispose, there must be some means by which the base class can expose its own disposed logic to the derived class, so the derived class' IDisposable.Dispose routine can call it.
There are a number of ways by which at least one of these conditions could be met; in different situations, different methods might be optimal. Most notably, for classes which have a public Dispose() method which will be semantically identical to IDisposable.Dispose(), it would be easiest to simply have the base class have a public virtual Dispose() method which implicitly implements IDisposable.Dispose. If a derived class overrides that method, it will override the behavior of IDisposable.Dispose, but its Dispose() can call base.Dispose() to activate the parent's dispose logic. This approach has one weakness, however: some class might not want to have a public Dispose() method which is semantically identical to IDisposable.Dispose(). While it might have been workable to use that approach for classes where it is suitable, and some other approach for other classes, Microsoft decided it would be better to have a common approach for all classes.
The idea is that all inheritable classes which implement IDisposable will have a protected virtual method whose signature doesn't match the possibly-public "void Dispose()"; IDisposable.Dispose() will call this method (with a parameter value of True) for all of its disposal logic, and a derived class which overrides this method may call the base disposal logic by calling the corresponding method of its parent. Although Microsoft allowed for the possiblity of a "Finalize" method calling this method with a value of false, there isn't really any need for that. Adding a Finalize method (or C# destructor) to a class which doesn't include all the provisions required for one--including "GC.KeepAlive() calls at key places) can be a breaking change which causes subtle bugs. If a class will need to use unmanaged resources but the parent class does not, that should be handled by defining new finalizable classes to encapsulate unmanaged resources into managed objects, and then have the inherited class hold those managed objects.