How the CLR handles local variables with function scope in case an exception is thrown.
is it a must to use the finally block or the variable is disposed once the flow leaves the function
below is a small example
protected void FunctionX()
{
List<Employee> lstEmployees;
try
{
lstEmployees= new List<Employee>();
int s = lstEmployees[1].ID; // code intended to throw exception
}
catch (Exception ex)
{
ManageException(ex, ShowMessage); //exception is thrown here
}
finally { lstEmployees= null; } // Is the finally block required to make sure the list is cleaned
}
To answer your specific question, no, the finally block you've listed is not required.
Assigning null to a reference variable does not actually do anything, as garbage collection is non-deterministic. As a simplistic explanation, from time to time, the garbage collector will examine the objects within the heap to determine if there are any active references to them (this is called being "rooted"). If there are no active references, then these references are eligible for garbage collection.
Your assignment to null is not required, as once the function exits, the lstEmployees variable will fall out of scope and will no longer be considered an active reference to the instance that you create within your try block.
There are certain types (both within .NET and in third-party libraries) that implement the IDisposable interface and expose some deterministic cleanup procedures through the Dispose() function. When using these types, you should always call Dispose() when you're finished with the type. In cases where the lifetime of the instance shouldn't extend outside of the lifetime of the function, then you can use a using() { } block, but this is only required if the type implements IDisposable, which List<T> (as you used in your example) does not.
Don't be worried about the objects cleanup, that's why the .NET and most modern languages provide the garbage collection functionality in runtime.
If your object has a handle to unmanaged resource do that cleanup.
Some of the other answers are slightly misleading here.
In fact, the garbage collector has got (almost) nothing to do with the variable lstEmployees. But it never needs to be set to null, neither in normal code flow nor after an exception is thrown.
Setting references to null to free the object they point they point to is almost never required, especially not for local objects.
As a consequence, the garbage collector won’t care about the exception either.
On the other hand, unmanaged resources which aren’t handled by the CG do always require manual cleanup (via the Dispose method of the IDisposable interface). To make sure that such resources are returned after an exception was thrown, you indeed need the finally clause. Or, if you don’t intend to handle the exception locally, you can replace the try … finally by a using clause:
using (someUnmanagedResource) {
// … use the resource …
}
// Will implicitly call someUnmanagedResource.Dispose() *whatever happens*!
.NET languages are garbage collected, which means that objects lifetimes are kept track of, so the garbage collection will get rid of your list when it finds no more object references to it.
Not at all. When the variable is out of scope, the garbage collector will take care of it (when the GC decides it's time to collect all the garbage...)
The only thing you have to take in account is that maybe you don't want to wait for the GC to do its job, so resources help by an instance of a class are released (e.g. imagine you have locally created an instance that hols a reference to a database connection. The connection will be held until GC takes care of deleting the instance, and later on deleting the referenced connection, which may take a while).
In these cases, take a look at the IDisposable interface, so you can proactively free resources before your instances are removed by the GC.
.NET's garbage collector will handle this for you. In fact, setting "lastEmployees" to null accomplishes the same thing as just exiting the function.
Any item that is no longer referenced by the root application in one form or another will be marked for collection.
In .NET, you never need to worry about cleaning up managed resource. Hence, managed.
http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx
Related
Until recently it never really bothered me as to how to best declare and dispose of a local variable but I thought I'd ask once and for all and get some feedback as it's starting to bug me more and more these days.
When creating a function/method that creates a local object, which method is best to create and dispose of the object.
For simplicity sake, assume that the method of the object being called will never generate an exception i.e. ConvertThisToString
private string myFirstFunction()
{
MyDataType myObject = null;
try
{
myObject = new MyDataType();
return myOjbect.ConvertThisToString();
}
finally
{
myObject = null;
}
}
or
private string mySecondFunction()
{
MyDataType myObject = new MyDataType();
return myOjbect.ConvertThisToString();
}
Are both functions ok and is it just about coding preferences or is there one method that's better than the other? Why?
My opinion is that one always requires the try/catch in order to nullify the object, which might be an overkill of try/catch for nullifying's sake, while the other method doesn't call any explicit way to destroy the object, which might be to reliant on .NET GC to release it from memory.
Should I be using the "using" statement instead?
Well, this is probably an incorrect statement. Is a local object immediately destroyed and disposed of when leaving a function or will it be cleared at a later stage by the GC management or other.
Thanks for feedback.
Thierry
UPDATED:
Removed the catch block as it caused confusion in my question. Should haven't been there in the first place since I did say, no error would ever occur.
That's very wrong.
Don't swallow exceptions.
Assigning a variable to null at the end of its scope will not help the GC at all.
If your object actually has expensive resources, it should implement IDisposable (correctly!), and you should dispose it using a using statement (but only when you're finished with it!)
You don't need to assign to null. When the object leaves scope, it will automatically be eligible for GC. There is no need to do anything special.
Basically, just write the second, simple version.
Should I be using the "using" statement instead?
If your object is wrapping resources (not memory allocated via new ..., but native resources) and implements IDisposable, then yes, you should use the using statement to guarantee those are cleaned up.
Is a local object immediately destroyed and disposed of when leaving a function or will it be cleared at a later stage by the GC management or other.
It will become eligible to be collected. At some point in the future, the GC will clean it up, but the time when this happens in indeterminant.
The best approach here is the Using statement.
something like this:
private string myFirstFunction()
{
using(MyDataType myObject = new MyDataType())
{
return myObject.ConvertThisToString();
}
}
this will dispose the object after execution.
As with almost everything, it all depends on what object you are using. If the object you are creating implements IDisposable then you would be best served to place in a using (typically). Outside of that most objects will get cleaned up by the garbage collector. IF you are the producer of a class that accesses COM objects then as the producer you should have provided a away for a proper cleanup, e.g. implement the IDisposable interface and handle the Dispose() correctly. As others have commented swallowing exceptions or even try/catching EVERY method doesn't seem like a reasonable or good idea. If a call you are making has the potential of throwing an exception and you have unmanaged or leaky objects then you should handle via a try/finally or a using (again, if appropriate).
You don't need to use a try/catch/finally to set a variable to null. The .NET GC will clear up any unreferenced classes when a method ends in it's own time.
If you are doing something really intensive (more so than your sample shows) then you can set the variable reference to null as a pointer to the GC that this is no longer referenced. This will only make a difference to your program if you are doing something which ends up marking the variable reference for Gen2 collection and then you do more stuff which prevents the GC collecting your variable (because the scope has not been left - in this case the method).
This is a bit of an extreme case as the .NET GC is designed to remove this aspect of programming from your daily concern, and regardless, it should get cleared up when the scope ends - it might just a bit longer.
You use 'using' if the referenced object implements IDisposable, and you do this typically to release unmanaged resources - though there may be other reasons why a class implements this interface.
Your first method is total overkill... it should just be as described in MySecondFunction(), and just don't swallow exceptions (I'm referring to the empty catch block) like that - because it leads to buggy, unmaintanable code! :)
I have a class that should delete some file when disposed or finalized. Inside finalizers I can't use other objects because they could have been garbage-collected already.
Am I missing some point regarding finalizers and strings could be used?
UPD: Something like that:
public class TempFileStream : FileStream
{
private string _filename;
public TempFileStream(string filename)
:base(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
{
_filename = filename;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_filename == null) return;
try
{
File.Delete(_filename); // <-- oops! _filename could be gc-ed already
_filename = null;
}
catch (Exception e)
{
...
}
}
}
Yes, you can most certainly use strings from within a finalizer, and many other object types.
For the definitive source of all this, I would go pick up the book CLR via C#, 3rd edition, written by Jeffrey Richter. In chapter 21 this is all described in detail.
Anyway, here's what is really happening...
During garbage collection, any objects that have a finalizer that still wants to be called are placed on a special list, called the freachable list.
This list is considered a root, just as static variables and live local variables are. Therefore, any objects those objects refer to, and so on recursively is removed from the garbage collection cycle this time. They will survive the current garbage collection cycle as though they weren't eligible to collect to begin with.
Note that this includes strings, which was your question, but it also involves all other object types
Then, at some later point in time, the finalizer thread picks up the object from that list, and runs the finalizer on those objects, and then takes those objects off that list.
Then, the next time garbage collection runs, it finds the same objects once more, but this time the finalizer no longer wants to run, it has already been executed, and so the objects are collected as normal.
Let me illustrate with an example before I tell you what doesn't work.
Let's say you have objects A through Z, and each object references the next one, so you have object A referencing object B, B references C, C references D, and so on until Z.
Some of these objects implement finalizers, and they all implement IDisposable. Let's assume that A does not implement a finalizer but B does, and then some of the rest does as well, it's not important for this example which does beyond A and B.
Your program holds onto a reference to A, and only A.
In an ordinary, and correct, usage pattern you would dispose of A, which would dispose of B, which would dispose of C, etc. but you have a bug, so this doesn't happen. At some point, all of these objects are eligible for collection.
At this point GC will find all of these objects, but then notice that B has a finalizer, and it has not yet run. GC will therefore put B on the freachable list, and recursively take C, D, E, etc. up to Z, off of the GC list, because since B suddenly became in- eligible for collection, so does the rest. Note that some of these objects are also placed on the freachable list themselves, because they have finalizers on their own, but all the objects they refer to will survive GC.
A, however, is collected.
Let me make the above paragraph clear. At this point, A has been collected, but B, C, D, etc. up to Z are still alive as though nothing has happened. Though your code no longer has a reference to any of them, the freachable list has.
Then, the finalizer thread runs, and finalizes all of the objects in the freachable list, and takes the objects off of the list.
The next time GC is run, those objects are now collected.
So that certainly works, so what is the big bruaha about?
The problem is with the finalizer thread. This thread makes no assumptions about the order in which it should finalize those objects. It doesn't do this because in many cases it would be impossible for it to do so.
As I said above, in an ordinary world you would call dispose on A, which disposes B, which disposes C, etc. If one of these objects is a stream, the object referencing the stream might, in its call to Dispose, say "I'll just go ahead and flush my buffers before disposing the stream." This is perfectly legal and lots of existing code do this.
However, in the finalization thread, this order is no longer used, and thus if the stream was placed on the list before the objects that referenced it, the stream is finalized, and thus closed, before the object referencing it.
In other words, what you cannot do is summarized as follows:
You can not access any objects your object refer to, that has finalizers, as you have no guarantee that these objects will be in a usable state when your finalizer runs. The objects will still be there, in memory, and not collected, but they may be closed, terminated, finalized, etc. already.
So, back to your question:
Q. Can I use strings in finalizer method?
A. Yes, because strings do not implement a finalizer, and does not rely on other objects that has a finalizer, and will thus be alive and kicking at the time your finalizer runs.
The assumption that made you take the wrong path is the second sentence of the qustion:
Inside finalizers I can't use other objects because they could have been garbage-collected already.
The correct sentence would be:
Inside finalizer I can't use other objects that have finalizers, because they could have been finalized already.
For an example of something the finalizer would have no way of knowing the order in which to correctly finalize two objects, consider two objects that refer to each other and that both have finalizers. The finalizer thread would have to analyze the code to determine in which order they would normally be disposed, which might be a "dance" between the two objects. The finalizer thread does not do this, it just finalizes one before the other, and you have no guarantee which is first.
So, is there any time it is safe to access objects that also have a finalizer, from my own finalizer?
The only guaranteed safe scenario is when your program/class library/source code owns both objects so that you know that it is.
Before I explain this, this is not really good programming practices, so you probably shouldn't do it.
Example:
You have an object, Cache, that writes data to a file, this file is never kept open, and is thus only open when the object needs to write data to it.
You have another object, CacheManager, that uses the first one, and calls into the first object to give it data to write to the file.
CacheManager has a finalizer. The semantics here is that if the manager class is collected, but not disposed, it should delete the caches as it cannot guarantee their state.
However, the filename of the cache object is retrievable from a property of the cache object.
So the question is, do I need to make a copy of that filename into the manager object, to avoid problems during finalization?
Nope, you don't. When the manager is finalized, the cache object is still in memory, as is the filename string it refers to. What you cannot guarantee, however, is that any finalizer on the cache object hasn't already run.
However, in this case, if you know that the finalizer of the cache object either doesn't exist, or doesn't touch the file, your manager can read the filename property of the cache object, and delete the file.
However, since you now have a pretty strange dependency going on here, I would certainly advice against it.
Another point not yet mentioned is that although one might not expect that an object's finalizer would ever run while an object is in use, the finalization mechanism does not ensure that. Finalizers can be run in an arbitrary unknown threading context; as a consequence, they should either avoid using any types that aren't thread-safe, or should use locking or other means to ensure that they only use things in thread-safe fashion. Note finalizers should use Monitor.TryEnter rather than Monitor.Enter, and endeavor to act as gracefully as possible if a lock is unexpectedly held. Note that since finalizers aren't supposed to run while an object is still in use, the fact that a lock was unexpectedly held will often suggest that a finalizer was run early. Depending upon the design of the code which uses the lock, it may be possible to have the finalizer set a flag and try again to acquire the lock, and have any other code which uses the lock check after releasing it whether that flag is set and, if so, reregister the object for finalization.
Handling finalization cleanup correctly in all threading scenarios is difficult. Finalization might not seem complicated, but no convenient automated mechanisms exist by which objects can ensure that finalizers won't run while the objects in question are in use. Consequently, finalizers have a lot of subtle thread-safety issues. Code which ignores such issues will "usually" work, but may sometimes fail in difficult-to-diagnose ways.
You can call the dispose method inside your finalizer and have the file cleanup code in the Dispose method. Along with that you can also pass a boolean to your dispose method that indicates that you are invoking it from the finalizer.
For an excellent reference on the proper usage of Dispose and Fianlizers , read this Proper use of the IDisposable interface
The question is self explanatory :
Foo objfoo;
try
{
objfoo = new Foo();
..........
.........
}
catch
{
}
finally
{
objfoo = null;
}
Is it necessary to free objects like this ?
Note: Setting a local / field to null is not freeing the value. It is instead removing a reference to the value which may or may not make it elligable for collection during the next GC cyle.
To answer the question, no it is not necessary. The JIT`er will calculate the last time a local is used and will essentially remove the local as one of the object's GC roots at that time. Nulling the local out will not speed up this process.
Raymond Chen did an excellent article on this very subject
http://blogs.msdn.com/b/oldnewthing/archive/2010/08/10/10048149.aspx
You dont need to as objFoo will be eligible for garbage collection (as per your code) once you leave the try block. objfoo =null just sets the pointer to null, if any other code had a pointer to the object then it wont be garbage collected
Assigning null to a variable will not delete the object it points to.
You don't need to worry about memory cleanup. C# will do it automatically for you, if you're using .NET.
In C#, usually not, because your objects will be freed by the Garbage Collector. Setting it to null later might even extend its lifetime because (depending how the compiler optimizes your code) it is still referenced at that point.
An exception is if the object implements IDisposable, which should be disposed using its Dispose() method. But you usually wrap those in using-blocks.
No , its not necessary , let the CLR do its job.
Unless the objects are accessing unmanaged resources (files, network shares, database connections ...) there is no need to do this, since they will be marked for garbage collection once they are out of scope.
If they are using resources (the StreamReader class for example) it's necessary to dispose of the objects yourself, but that's best accomplished by using a using statement.
Automatic Garbage Collection means you do not need to free memory resources, i.e. objects created with new.
You may need to free other resources you have allocated, eg locking mutexes and maybe context specific to your own project, for which you have the finally block.
There' typically no need to do this. If your function is about to exit then your object will automatically become eligible for garbage collection.
However, if you've got a really long function or it's going to do some blocking operation after the finally block then by setting the variable to null you make it eligible for garbage collection immediately. This might be a good idea if Foo manages a large amount of data, for example.
Can I trust that an object is destroyed and its destructor is called immediately when it goes out of scope in C#?
I figure it should since many common coding practices (e.g. transaction objects) rely on this behaviour, but I'm not very used to working with garbage collection and have little insight to how such languages usually behave.
Thanks.
Nope, .Net and hence C# relies on a garbage collection memory management. So destructors (which in .Net is called finalizers) are not called until GC finds it proper to destroy the objects.
Additionally: most "regular" objects in C# don't have destructors. If you need the destructor pattern you should implement the IDisposable interface with the Dispose Pattern. On disposable objects you should also make sure that the Dispose method gets called, either with the using keyword or directly calling the method.
To further (hopefully) clarify: deterministic disposal is useful in .Net e.g. when you need to explicitly free resources that is not managed by the .Net runtime. Examples of such resources are file handles, database connections, etc. It is usually important that these resources be freed as soon as they no longer are needed. Thus we cannot afford to wait for the GC to free them.
In order to get deterministic disposal (similar to the scope behavior of C++) in the non-deterministic world of the .Net GC, the .Net classes rely on the IDisposable interface. Borrowing from the Dispose Pattern, here are some examples:
First, instantiating a disposable resource and then letting the object go out of scope, will leave it up to the GC to dispose the object:
1. {
2. var dr = new DisposableResource();
3. }
To fix this we can explicitly dispose the object:
1. {
2. var dr = new DisposableResource();
3.
4. ...
5.
6. dr.Dispose();
7. }
But what if something goes wrong between line 2 and 6? Dispose will not be called. To further ensure that Dispose will finally be called regardless of any exceptions we can do the following:
1. var dr = new DisposableResource();
2. try
3. {
4. ...
5. }
6. finally
7. {
8. dr.Dispose();
9. }
Since this pattern is often needed, C# includes the using keyword to simplify things. The following example is equivalent to the above:
1. using (var dr = new DisposableResource())
2. {
3. ...
4. }
No. An object doesn't actually go "out of scope," the reference to it (i.e. the variable you use to access it) does.
Once there are no more references to a given object, that object becomes eligible for garbage collection (GC) should the need arise. Whenever the GC decides it needs to reclaim the space your no-longer-referenced object, that's when the objects finalizer will be called.
If your object is a resource (e.g. a file handle, database connection), it should implement the IDisposable interface (which obligates the object to implement a Dispose() method to clean up any open connections, etc). The best practice for you in this case would be to create the object as part of a using block, so that when this block is completed, your application will automatically call the objects Dispose() method, which will take care of closing your file/db connection/whatever.
e.g.
using (var conn = new DbConnection())
{
// do stuff with conn
} // conn.Dispose() is automatically called here.
The using block is just some syntactic sugar which wraps your interactions with the conn object in a try block, along with a finally block which only calls conn.Dispose()
There is no such thing als a C++-like destructor in C#. (There is a different concept of destructor in C#, also called a finalizer, which uses the same syntax as C++ destructors, but they are unrelated to destroying objects. They're intended to provide a cleanup mechanism for unmanaged resources.)
The garbage collector will cleanup objects sometime after they are no longer referenced. Not immediately, and there is no way to guarantee this either.
Luckily there is also no real reason why you would want to guarantee this. If you need the memory, then the GC will reclaim it then. If you don't, why care if there's still some garbage object around? It's not a memory leak: the GC can still find it and clean it up any time.
No, this isn't guaranteed. Similar to languages such as Java, in C# the garbage collector runs when it's needed (i. e. when the heap is getting too full). However, when your objects implement IDisposable, i. e. they have a Dispose() method and it has to be called, then you can take advantage of the using keyword:
using (var foo = new DisposableObject()) {
// do something with that
}
That way Dispose() will be called immediately when leaving that using block.
Note: IDisposable is found in many types, most notably GDI+ but also database connections, transactions, etc. so it may really be the right pattern here.
Note 2: Behind the scenes above block will get translated into a try/finally block:
var foo = new DisposableObject();
try
{
// do something with that
}
finally
{
foo.Dispose();
}
But that translation is done by the compiler and very handy for not forgetting to call Dispose().
I don't think you should rely on garbage collectors in this way. Even if you deduct how they operate it might very well be that in the next release they've reimplemented it.
In any case, objects are not garbage collected the moment you unreference them. Typically they are collected until some threshold is reached and then they are released.
Especially in java programs this is very noticeable when you look at the memory consumption on the task manager. It grows and grows and all of a sudden every minute it drops again.
No. If you refer to CLI specification (p. 8.9.6.7 about Finalizers) http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf you can find the following
the CLI should ensure that finalizers are called soon after the instance becomes
inaccessible. While relying on memory pressure to
trigger finalization is acceptable, implementers should consider the use of additional
metrics
but it must not.
I've got a C# class with a Dispose function via IDisposable. It's intended to be used inside a using block so the expensive resource it handles can be released right away.
The problem is that a bug occurred when an exception was thrown before Dispose was called, and the programmer neglected to use using or finally.
In C++, I never had to worry about this. The call to a class's destructor would be automatically inserted at the end of the object's scope. The only way to avoid that happening would be to use the new operator and hold the object behind a pointer, but that required extra work for the programmer isn't something they would do by accident, like forgetting to use using.
Is there any way to for a using block to be automatically used in C#?
Many thanks.
UPDATE:
I'd like to explain why I'm not accepting the finalizer answers. Those answers are technically correct in themselves, but they are not C++ style destructors.
Here's the bug I found, reduced to the essentials...
try
{
PleaseDisposeMe a = new PleaseDisposeMe();
throw new Exception();
a.Dispose();
}
catch (Exception ex)
{
Log(ex);
}
// This next call will throw a time-out exception unless the GC
// runs a.Dispose in time.
PleaseDisposeMe b = new PleaseDisposeMe();
Using FXCop is an excellent suggestion, but if that's my only answer, my question would have to become a plea to the C# people, or use C++. Twenty nested using statements anyone?
Where I work we use the following guidelines:
Each IDisposable class must have a finalizer
Whenever using an IDisposable object, it must be used inside a "using" block. The only exception is if the object is a member of another class, in which case the containing class must be IDisposable and must call the member's 'Dispose' method in its own implementation of 'Dispose'. This means 'Dispose' should never be called by the developer except for inside another 'Dispose' method, eliminating the bug described in the question.
The code in each Finalizer must begin with a warning/error log notifying us that the finalizer has been called. This way you have an extremely good chance of spotting such bugs as described above before releasing the code, plus it might be a hint for bugs occuring in your system.
To make our lives easier, we also have a SafeDispose method in our infrastructure, which calls the the Dispose method of its argument within a try-catch block (with error logging), just in case (although Dispose methods are not supposed to throw exceptions).
See also: Chris Lyon's suggestions regarding IDisposable
Edit:
#Quarrelsome: One thing you ought to do is call GC.SuppressFinalize inside 'Dispose', so that if the object was disposed, it wouldn't be "re-disposed".
It is also usually advisable to hold a flag indicating whether the object has already been disposed or not. The follwoing pattern is usually pretty good:
class MyDisposable: IDisposable {
public void Dispose() {
lock(this) {
if (disposed) {
return;
}
disposed = true;
}
GC.SuppressFinalize(this);
// Do actual disposing here ...
}
private bool disposed = false;
}
Of course, locking is not always necessary, but if you're not sure if your class would be used in a multi-threaded environment or not, it is advisable to keep it.
Unfortunately there isn't any way to do this directly in the code. If this is an issue in house, there are various code analysis solutions that could catch these sort of problems. Have you looked into FxCop? I think that this will catch these situations and in all cases where IDisposable objects might be left hanging. If it is a component that people are using outside of your organization and you can't require FxCop, then documentation is really your only recourse :).
Edit: In the case of finalizers, this doesn't really guarantee when the finalization will happen. So this may be a solution for you but it depends on the situation.
#Quarrelsome
If will get called when the object is moved out of scope and is tidied by the garbage collector.
This statement is misleading and how I read it incorrect: There is absolutely no guarantee when the finalizer will be called. You are absolutely correct that billpg should implement a finalizer; however it will not be called automaticly when the object goes out of scope like he wants. Evidence, the first bullet point under Finalize operations have the following limitations.
In fact Microsoft gave a grant to Chris Sells to create an implementation of .NET that used reference counting instead of garbage collection Link. As it turned out there was a considerable performance hit.
~ClassName()
{
}
EDIT (bold):
If will get called when the object is moved out of scope and is tidied by the garbage collector however this is not deterministic and is not guaranteed to happen at any particular time.
This is called a Finalizer. All objects with a finaliser get put on a special finalise queue by the garbage collector where the finalise method is invoked on them (so it's technically a performance hit to declare empty finalisers).
The "accepted" dispose pattern as per the Framework Guidelines is as follows with unmanaged resources:
public class DisposableFinalisableClass : IDisposable
{
~DisposableFinalisableClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// tidy managed resources
}
// tidy unmanaged resources
}
}
So the above means that if someone calls Dispose the unmanaged resources are tidied. However in the case of someone forgetting to call Dispose or an exception preventing Dispose from being called the unmanaged resources will still be tidied away, only slightly later on when the GC gets its grubby mitts on it (which includes the application closing down or unexpectedly ending).
The best practice is to use a finaliser in your class and always use using blocks.
There isn't really a direct equivalent though, finalisers look like C destructors, but behave differently.
You're supposed to nest using blocks, that's why the C# code layout defaults to putting them on the same line...
using (SqlConnection con = new SqlConnection("DB con str") )
using (SqlCommand com = new SqlCommand( con, "sql query") )
{
//now code is indented one level
//technically we're nested twice
}
When you're not using using you can just do what it does under the hood anyway:
PleaseDisposeMe a;
try
{
a = new PleaseDisposeMe();
throw new Exception();
}
catch (Exception ex) { Log(ex); }
finally {
//this always executes, even with the exception
a.Dispose();
}
With managed code C# is very very good at looking after its own memory, even when stuff is poorly disposed. If you're dealing with unmanaged resources a lot it's not so strong.
This is no different from a programmer forgetting to use delete in C++, except that at least here the garbage collector will still eventually catch up with it.
And you never need to use IDisposable if the only resource you're worried about is memory. The framework will handle that on it's own. IDisposable is only for unmanaged resources like database connections, filestreams, sockets, and the like.
A better design is to make this class release the expensive resource on its own, before its disposed.
For example, If its a database connection, only connect when needed and release immediately, long before the actual class gets disposed.