|
Not quite.
If you do absoutly nothing at all, no dispose method, no finalizer, nothing. Then what will happen is that all objects that needed disposing of (like the component object in your example) will eventually get cleaned up by the GC which will call the finalizers. This isn't great though. Objects that have to be finalized have to go onto the finalizer queue, which means they stay in memory longer (They survive one GC generation longer) so your memory usage is higher, and resources aren't freed up when they're finished with, it may be quite a while before the finalizer gets called. But yes, eventually all managed resources will get cleaned up by the GC finalizer thread. And thus, any native resources wrapped by the managed classes will also get cleaned up.
However, if you directly use a native resource yourself there is nothing to clean it up. If you use a native resource directly, you must make sure you clean it up! if you don't, you have a memory leak.
The handy thing is, if you implement the dispose pattern on your class, then you are wrapping the native resouce yourself, so users of your class don't have to worry about it, so if users of your class forget to call dispose, you don't have to worry because your classes finalizer will eventually do the work.
Simon
|
|
|
|
|
Cool, Simon!
I want to confirm with you an important point that, if we do not release native resource like file handle in either Dispose method or Finalizer method, GC will not release such native resource, right?
regards,
George
|
|
|
|
|
|
Thanks Zoltan,
Cool!
regards,
George
|
|
|
|
|
The thing is that in .Net we have undeterministic finalization meaning that the Finalize() method will be called at an undetermined time in the future. The solution to this is to have deterministic finalization by implementing the Dispose pattern. You should have your cleanup code in Dispose() and if you implement the Finalize() method that should call on Dispose.
George_George wrote: BTW: if the derived class manages native resource, I think it needs to have a destructor. Any comments?
No, implement the Dispose pattern and release the native resources there. Implementing a destructor is not the best solution because you don't know when the GC will finalize the object.
For more info check out this article[^]
|
|
|
|
|
Thanks Simon,
I think the correct pattern should be, the derived class should only implement Dispose, but not Finalize, right?
regards,
George
|
|
|
|
|
You can implement Finalize too and in the Finalize() method just call the Dispose() method.
|
|
|
|
|
Thanks Zoltan,
You mean from base to derived class to most derived class, all implements Finalize method and in Finalize method call Dispose?
regards,
George
|
|
|
|
|
Hi gurus, I have this method in one of my classes:
public static Forum GetForumByID(int forumID)
{
Forum forum = null;
foreach (Forum theForum in GetForums())
{
if (theForum.ID == forumID)
{
forum = theForum;
break;
}
}
if (forum == null)
{
throw new ForumNotFoundException(forumID);
}
return forum;
}
Now, I thought I'd rewrite the method to be like that:
public static Forum GetForumByID(int forumID)
{
foreach (Forum forum in GetForums())
{
if (forum.ID == forumID)
return forum;
}
throw new ForumNotFoundException(forumID);
}
My question is, is there any thing wrong with that code? It's perfectly accepted by the compiler (as you know nothing is executed after an exception is thrown). Actually I never write such code, so this is going to be the first time but I want to know whether there's any problem with that code, also whether you believe it's a bad practice or coding style and why.
Your help is much appreciated ...
|
|
|
|
|
Waleed Eissa wrote: My question is, is there any thing wrong with that code?
Maybe. If not finding a forum is an "expected" condition then you shouldn't throw an "exception" for it.
led mike
|
|
|
|
|
Some ASP.NET controls requires this anti-pattern
|
|
|
|
|
I'm sorry, I didn't quite understand what you mean, could you please explain more?
|
|
|
|
|
an anti pattern is a case of BAD design. As opposed to a normal 'design pattern' which is a best practice way of doing something.
You know, every time I tried to win a bar-bet about being able to count to 1000 using my fingers I always get punched out when I reach 4....
-- El Corazon
|
|
|
|
|
Thanks for your answer dan, well, usually you should use exceptions for handling unexpected conditions which is true in my case (at least in my understanding), I'm not using exceptions to control the flow of my application ...
|
|
|
|
|
Sorry, it looks like Leppie and I were talking at cross purposes to you. His point was that exceptions for normal process flow is a relatively common anti-pattern and some ASP.net controls were written such that it was needed. That was mostly directed to Led Mike's post.
You know, every time I tried to win a bar-bet about being able to count to 1000 using my fingers I always get punched out when I reach 4....
-- El Corazon
|
|
|
|
|
There is no difference between the two implementations, but the second one is more concise and easier to read (= good).
All led meant about the exceptions is that exceptions should only be used in truly exceptional cases. If not being able to find a forum based on its id is an "expected" condition, then a better idea would be to return null and have the calling function check the return value.
Great article about using exceptions: http://codebetter.com/blogs/karlseguin/archive/2006/04/05/142355.aspx[^]
|
|
|
|
|
yes this is true for library code. Design for libraries is different in some respects from design for application level code since they must consider the fact that they don't have access to application level code to change it. Kent Beck has entire chapters on developing libraries in "Implementation Patterns".
led mike
|
|
|
|
|
Thanks for your reply, actually it's not an expected condition, it probably should never happen unless someone intentionally changes the query string of the page (it's a web application)
|
|
|
|
|
They are one and the same thing. For style, I prefer the 2nd listing, but either is acceptable.
|
|
|
|
|
I prefer the first, because it makes it clear why the exception is being thrown.
Pits fall into Chuck Norris.
|
|
|
|
|
Brady Kelly wrote: because it makes it clear why the exception is being thrown.
That should be documented instead
|
|
|
|
|
It is documented, by the guard statement.
|
|
|
|
|
If you're using the latest and greatest C# 3, I prefer this:
var forumWithId = (from f in GetForums() where f.ID == forumID select f).FirstOrDefault(); or if you prefer the method syntax,
var forumWithId = forums.FirstOrDefault(f => f.ID == forumID);
|
|
|
|
|
Hi,
the second snippet is fine.
Whether you end with a throw or just return null is up to you.
Luc Pattyn [Forum Guidelines] [My Articles]
This month's tips:
- before you ask a question here, search CodeProject, then Google;
- the quality and detail of your question reflects on the effectiveness of the help you are likely to get;
- use PRE tags to preserve formatting when showing multi-line code snippets.
|
|
|
|
|
The second is clearer, but breaking/returning out of a foreach is generally poor style; use it sparingly.
|
|
|
|