可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am confused about dispose. I am trying to get my code disposing resources correctly. So I have been setting up my classes as IDisposable (with a Dispose method) them making sure that the Dispose method gets called.
But now FXCop is telling me lots of stuff about Disposing = false and calling Dispose(false).
I don't see a Dispose method that takes a bool. Do I need to make one? If so, why? Why not just have a method that gets called when it is disposing?
I saw some code here: http://msdn.microsoft.com/en-us/library/ms244737.aspx that shows how to make a Disposing method that takes a bool. It says it is for native vs managed resourses. But I thought the whole point of dispose was for unmanaged resourses only.
Also, the line that FXCop is complaining about is this:
~OwnerDrawnPanel()
{
_font.Dispose();
}
It says:
CA1063 : Microsoft.Design : Modify 'OwnerDrawnPanel.~OwnerDrawnPanel()' so that it calls Dispose(false) and then returns.
But Font does not have a Dispose(bool) on it (that I can find).
To sum it up:
Why do I need a Dispose(bool)? and if I do, why doesn't Font have it? and since it does not have it, why is FXCop asking me to use it?
Thanks for all the great answers. I think I understand now. Here is
The answer as I see it:
Disposing of "unmanaged" resources falls into two categories:
- Resources that are wrapped in a managed class (ie Bitmap, Font etc), but still need Dispose to be called to clean them up properly.
- Resources that you have allocated, which are representations of native resources (ie device contexts that need to be released)
Dispose(bool) is used to tell the difference between the two:
- When Dispose is directly called on your object, you want to free both kinds of "unmanaged" resources.
- When your object is up for Garbage Collection, you don't need to worry about the first kind of resources. The garbage collector will take care of them when it cleans them up. You only need to worry about true native resources that you have allocated (if any).
回答1:
IDisposable
provides a method with the signature
public void Dispose()
Microsoft best practices (http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx) recommend making a second private method with the signature
private void Dispose(bool)
Your public Dispose method and Finalizer should call this private Dispose method to prevent disposing managed resources multiple times.
You can fix the warning you are getting by either implementing IDisposable and disposing of your font object in the dispose method, or creating a Dispose(bool)
method in your class, and make your finalizer call that method.
回答2:
Dispose(bool)
is a pattern to implement Finalize
and Dispose
to Clean Up Unmanaged Resources , see this for detail
回答3:
Dispose(bool)
is not meant to be public and that is why you don't see it on Font
.
In case some user of your class forgets to call Dispose on your method, you will release the unmanaged resources only by making a call to Dispose(false)
in the Finalizer
.
In case IDispose is called correctly, you call the Dispose on managed resources and also take care of the unmanaged.
The flag is to distinguish the two cases.
It is a pattern recommended by MSDN.
回答4:
FxCop says you should implement the Disposable pattern like described here. Note that you should not use finalizers for disposing managed resources like _font
is. Finalizers are used for cleaning up unmanaged resources. If you do not execute the cleanup logic in the Dispose method of your (sub)class they are executed non-deterministically by the garbage collector.
回答5:
Also please note that it is very rarely that you need to do anything in the destructor. Regularly, everything is taken care of by the garbage collector. For example, in your code, you don't need to dispose the _font
object in the OwnerDrawnPanel
's destructor. Since the panel is getting cleaned up by the GC, so will be _font
, because panel was the only one who referenced it, right?
Generally, if you own disposable objects, you only need to dispose them when your own Dispose
method was called. But NOT in the destructor. When your destructor is running, you can bet that all your aggregated objects are being cleaned up as well.
回答6:
You should almost never need to use finalizers. They are only for classes that directly contain unmanaged resources, and in .NET 2.0+ those should be wrapped in SafeHandle.
回答7:
I think Dispose(true)
will free both the managed and unmanaged resource as we need to not call finalize again that's why we write GC.SupressFinalize()
after Dispose(true)
.
We call Dispose(false)
in destructors to free unmanaged resources and will be called by Runtime and not user's code.
回答8:
Agreeing with Kumar, the Dispose(bool disposing)
pattern is also documented on MSDN. The distinction is not between managed and unmanaged resources, but whether Dispose
is being called by your code or the runtime.
回答9:
I found a good article about correct implementation of IDispose interface: http://msdn.microsoft.com/en-us/library/ms244737(v=vs.80).aspx
回答10:
The pattern of implementing a public public void Dispose()
, protected virtual void Dispose(bool)
, and ~ClassName()
finalizers is a best practice recommended by Microsoft as a way to neatly organize your cleanup code for both managed and unmanaged resources.
Basically, the code that uses your Disposable
class should call Dispose()
, but if it doesn't, the finalizer ~ClassName()
will get called by Garbage Collection, and based on which one of those is used, you set the argument to Dispose(bool)
as true or false, and in your Dispose(bool)
, you only clean up managed resources if the argument is true.
The warning you are getting seems to specifically recommend that you use this practice in your finalize method ~ClassName()
.