I am developing a utility class that contains static methods that will be frequently called by multiple threads. I am noticing that memory use is growing over time, so it seems to me that I have some memory leaks.
Here is a simple example of the pattern I am using for these static methods:
public static int CreateNewThing(int IDofSomeDBObjectHoldingInfoToCreateNewThing)
{
using(SomeDBContext context = new SomeDBContext(connectionString))
{
SomeDBObjectHoldingInfoToCreateNewThing createNewThingyInfo = context.SomeDBObjectsHoldingInfoToCreateNewThing.First(obj => obj.ID == IDofSomeDBObjectHoldingInfoToCreateNewThing);
// Do some stuff to create the new object
// Return the ID of the newly created thingy...
return theNewThingThatWasCreated.ID;
}
}
My question is whether using 'using' statements or directly calling Dispose inside static methods actually clears up any memory. Granted, I haven't stated the overall architecture or purpose of this application, but I am also wondering if I'm using the best pattern here. What are the best practices for creating thread-safe utility classes in .NET?
I am noticing that memory use is growing over time, so it seems to me that I have some memory leaks.
Not necessarily - you'd need to give more data for us to really have a good idea about that.
My question is whether using 'using' statements or directly calling Dispose inside static methods actually clears up any memory.
using statements aren't about cleaning up memory. That's the GC's job. They're about releasing non-memory resources. Whether you're in a static method or not is completely irrelevant to whether the SomeDBContext ought to be disposed or not.
My question is whether using 'using' statements or directly calling Dispose inside static methods actually clears up any memory
using is just a syntactially simpler way of calling Dispose.
using(MyClass obj = new MyClass())
{
}
is just the same as writing:
MyClass obj;
try
{
obj = new MyClass()
}
finally
{
((IDisposable)obj).Dispose();
}
Next, does Dispose free up memory. No, it doesn't. Dispose is designed to release unmanaged resources that won't get cleaned up with then garbage collector releases the memory for this object. It doesn't actually release the memory for the object any quicker. Common things that need to be disposed of are network connections (as is the case here) file handles, unmanaged memory created through interopping with another language, etc.
So, why is your memory going up. In short, it's just the usual behavior. You are creating objects, they are using memory, so your memory is increasing. At some point the garbage collector will determine that it needs to perform a collection to free up some memory. (Possibly because the system is running low and it needs more, possibly because it has just been long enough, or whatever other conditions the C# language has specified. It almost always knows better than you when a collection is really needed.)
So until you have a real problem just don't worry about it, this is normal behavior in a managed language. If you start running out of memory, or having the memory not go down even when collections do occur, then you need to start looking for problems.
Related
I'm battling a bit to understand disposing of objects and garbage collection. In particular, I don't understand why I can still use a disposed object. I'm not trying to do anything practically, I'm just playing around with theory at the moment and in my understanding, I thought that I wouldn't be able to do the following:
class Program
{
static void Main(string[] args)
{
Person p = new Person();
using (p)
{
p.Name = "I am Name";
}
Console.WriteLine(p.Name); // I thought this would break because I've already disposed of p
Console.ReadLine();
}
}
public class Person : IDisposable
{
public string Name;
public void Dispose()
{
Console.WriteLine("I got killed...");
}
}
I'm hoping that someone could perhaps give me some direction or guidance here so as to clear up my misunderstanding of this concept?
Disposing of an object doesn't do anything magical - the CLR doesn't really care about IDisposable at all... it's just a framework interface that has support within C# (and other languages). Calling Dispose is just like calling other methods.
If you don't make a disposed object fail when you perform further operations on it, it won't. Indeed, there are some cases where you really want to be able to - for example, calling ToArray on MemoryStream is fine after it's disposed, even though you can't call Read etc. That can be really handy in situations where the writes to a MemoryStream are chained from a wrapper which will dispose of the MemoryStream, but you want the data afterwards.
In general though, you should code as if you can't use a disposed object after disposal, unless you know for sure that it still supports the operations you need. A default position of "I expect it will break..." is a safe one.
Dispose pattern is used when you have an object that uses unmanaged resources that needs to be freed when no longer needed. Managed resources are freed automatically by GC.
In your example, the string Name is a managed resource. If you had an opened file there, that would be an unmanaged resource. Dispose method would then care about closing the file handle, which would make the object's file access not usable after the Dispose. Yet still, you could ask for the Name, because until GC collects that object, it will exist.
Recommended reading: MSDN Dispose Pattern
IDisposable is convention to handle Unmanaged resource inside managed code.
You are implementing IDisposable interface, and later you are just doing Dispose() method call, not destructing or killing actual object
What is unmanaged resource ?
Unmanaged resource is resource which Garbage collector can not collect. for example memory that are allocated by other program or code outside managed code. So GC can not manage automaticly.
public struct LocalTLS : IDisposable
{
public byte[] bArr;
public string str;
public LocalTLS(int k)
{
str = "Labamba";
bArr = new byte[20000];
}
public void Dispose()
{
MessageBox.Show("In Dispose");
//Thread.FreeNamedDataSlot("jaja");
int k = 90;
k += 90;
}
}
private void buttonTLS_retreive_Click(object sender, EventArgs e)
{
LocalTLS lts = new LocalTLS(1);
}
After the click event returns I expect the Dispose call but THAT NEVER HAPPENS, Can Some one explain. I do not want to do any manual steps like calling Dispose or do using. I want that to happen automatically.
Well thanks for all your answers, I wanted to implement a a class for LocalDataStoreSlot, that will automatically free the Slot and it goes out of scope, as shown in the commented code. This will free the developer from remembering to
call dispose, wherein the actual FreeNamedDataSlot(...) happens. Seems like that is not possible
The CLR does not perform garbage collection all the time, otherwise your program will be very slow because it is performing GC. To perform GC, the CLR has to suspend ALL the threads before reclaiming memory used by out of scope objects. That is a very big performance impact.
The CLR will perform GC and call the object's Dispose method when necessary. Do not call the object's Dispose() method unless you have a good reason. If the object is associated to native system handles, network connections, file handles etc., those are good reasons to use the using keyword or call it's Dispose() method. Generally the CLR will GC objects that are out of scope fast enough such that your application will not run out of memory.
I understand your concern, you believe that byte[20000] is a significant memory footprint to your application and you want to control your memory usage carefully. But this is not C++. The CLR will automatically manage memory for you. In my past 7 years of .NET develop I have only come across one application where the default GC is not fast enough and I have to call Dispose() on objects manually. So in short, just hand over memory management to the CLR - it does a very good job.
p.s. if you're interested in how GC works internally, there are a number of in-depth articles online. Just search - you'll find them.
You've to wrap your object declaration inside using like this:
using(LocalTLS lts = new LocalTLS(1))
{
// use lts here
} // at this point, the Dispose method is called.
or call Dispose method manually:
lts.Dispose();
Also, the Dispose() method is automatically called when there is no reference to lts in the code, by the Garbage Collector.
Its a struct, it lives on the memory stack not the memory heap. So its not going to be collected by the garage collector like objects do, so the GC will not call the dispose method. Your struct "LocalTLS " will be freed up and taken off the memory stack when your method ends. When it does this, it does not look for the IDisposable interface.
I have an ASP.NET application that has multiple helper classes. I'm a little worried about Memory leaks. Each time i want to use a helper class member function i call them like this new SampleHandler().DoFunction();
Since it dosen't have any strong reference to the object created can I guarantee whether GC will clear the memory for the object created ? Since there is a high chance for me that I won't be using the object again in the page I started coding like this.
Note: There are numerous calls to various member functions belonging to different helper classes in the code behind file performed in the same way.
Yes, since there are no other outstanding references, the instance created by new SampleHandler() will be eligible for collection as soon as DoFunction() returns.
There is, however, no guarantee about the time when the GC will collect that instance, as usual.
The garbage collector will take care of unused references. So you don't need to worry about a memory leak. But if you create "garbage"-objects very fast you could have temporary memory pressure.
But if you don't need the instance anyway or the instances are exchangeable you should consider to make the method static.
public class SampleHandler
{
public static void DoFunction()
{
// ...
}
}
Then you would call it:
SampleHandler.DoFunction();
There is no problem with static methods in ASP.NET even if it's a multithreaded environment. But you should be careful with static fields.
It seems that in most cases the C# compiler could call Dispose() automatically. Like most cases of the using pattern look like:
public void SomeMethod()
{
...
using (var foo = new Foo())
{
...
}
// Foo isn't use after here (obviously).
...
}
Since foo isn't used (that's a very simple detection) and since its not provided as argument to another method (that's a supposition that applies to many use cases and can be extended), the compiler could automatically and immediately call Dispose() without the developper requiring to do it.
This means that in most cases the using is pretty useless if the compiler does some smart job. IDisposable seem low level enough to me to be taken in account by a compiler.
Now why isn't this done? Wouldn't that improve the performances (if the developpers are... dirty).
A couple of points:
Calling Dispose does not increase performance. IDisposable is designed for scenarios where you are using limited and/or unmanaged resources that cannot be accounted for by the runtime.
There is no clear and obvious mechanism as to how the compiler could treat IDisposable objects in the code. What makes it a candidate for being disposed of automatically and what doesn't? If the instance is (or could) be exposed outside of the method? There's nothing to say that just because I pass an object to another function or class that I want it to be usable beyond the scope of the method
Consider, for example, a factory patter that takes a Stream and deserializes an instance of a class.
public class Foo
{
public static Foo FromStream(System.IO.Stream stream) { ... }
}
And I call it:
Stream stream = new FileStream(path);
Foo foo = Foo.FromStream(stream);
Now, I may or may not want that Stream to be disposed of when the method exits. If Foo's factory reads all of the necessary data from the Stream and no longer needs it, then I would want it to be disposed of. If the Foo object has to hold on to the stream and use it over its lifetime, then I wouldn't want it to be disposed of.
Likewise, what about instances that are retrieved from something other than a constructor, like Control.CreateGraphics(). These instances could exist outside of the code, so the compiler wouldn't dispose of them automatically.
Giving the user control (and providing an idiom like the using block) makes the user's intention clear and makes it much easier to spot places where IDisposable instances are not being properly disposed of. If the compiler were to automatically dispose of some instances, then debugging would be that much more difficult as the developer had to decipher how the automatic disposal rules applied to each and every block of code that used an IDisposable object.
In the end, there are two reasons (by convention) for implementing IDisposable on a type.
You are using an unmanaged resource (meaning you're making a P/Invoke call that returns something like a handle that must be released by a different P/Invoke call)
Your type has instances of IDisposable that should be disposed of when this object's lifetime is over.
In the first case, all such types are supposed to implement a finalizer that calls Dispose and releases all unmanaged resources if the developer fails to do so (this is to prevent memory and handle leaks).
Garbage Collection (while not directly related to IDisposable, is what cleans up unused objects) isn't that simple.
Let me re-word this a little bit. Automatically calling Dispose() isn't that simple. It also won't directly increase performance. More on that a little later.
If you had the following code:
public void DoSomeWork(SqlCommand command)
{
SqlConnection conn = new SqlConnection(connString);
conn.Open();
command.Connection = conn;
// Rest of the work here
}
How would the compiler know when you were done using the conn object? Or if you passed a reference to some other method that was holding on to it?
Explicitly calling Dispose() or using a using block clearly states your intent and forces things to get cleaned up properly.
Now, back to performance. Simply calling Dispose() on an Object doesn't guarantee any performance increase. The Dispose() method is used for "cleaning up" resources when you're done with an Object.
The performance increase can come when using un-managed resources. If a managed object doesn't properly dispose of its un-managed resources, then you have a memory leak. Ugly stuff.
Leaving the determination to call Dispose() up to the compiler would take away that level of clarity and make debugging memory leaks caused by un-managed resources that much more difficult.
You're asking the compiler to perform a semantic analysis of your code. The fact that something isn't explicitly referenced after a certain point in the source does not mean that it isn't being used. If I create a chain of references and pass one out to a method, which may or may not store that reference in a property or some other persistent container, should I really expect the compiler to trace through all of that and figure out what I really meant?
Volatile entities may also be a concern.
Besides, using() {....} is more readable and intuitive, which is worth a lot in terms of maintainability.
As engineers or programmers, we strive to be efficient, but that is rarely the same thing as lazy.
Look at the MSDN Artilce for the C# Using Statement The using statement is just a short cut to keep from doing a try and finally in allot of places. Calling the dispose is not a low level functionality like Garbage Collection.
As you can see using is translated into.
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
How would the compiler know where to put the finally block? Does it call it on Garbage Collection?
Garabage Collection doesn't happen as soon as you leave a method. Read this article on Garbage Collection to understand it better. Only after there are no references to the object. A resource could be tied up for much longer than needed.
The thought that keeps popping into my head is that the compiler should not protect developers who do not clean up there resources. Just because a language is managed doesn't mean that it is going to protect from yourself.
C++ supports this; they call it "stack semantics for reference types". I support adding this to C#, but it will require different syntax (changing the semantics based on whether or not a local variable is passed to another method isn't a good idea).
I think that you are thinking about finalizers. Finalizers use the destructor syntax in c#, and they are called automatically by the garbage collector. Finalizers are only appropriate to use when you are cleaning up unmanaged resources.
Dispose is intended to allow for early cleanup of unmanaged resources (and it can be used to clean managed resources as well).
Detection is actually trickier than it looks. What if you have code like this:
var mydisposable = new...
AMethod(mydisposable);
// (not used again)
It's possible that some code in AMethod holds on to a reference to myDisposable.
Maybe it gets assigned to an instance variable inside of that method
Maybe myDisposable subscribes to an event inside of AMethod (then the event publisher holds a reference to myDisposable)
Maybe another thread is spawned by AMethod
Maybe mydisposable becomes "enclosed" by an anonymous method or lamba expression inside of AMethod.
All of those things make it difficult to know for absolute certain that your object is no longer in use, so Dispose is there to let a developer say "ok, I know that it's safe to run my cleanup code now);
Bear in mind also that dispose doesn't deallocate your object -- only the GC can do that. (The GC does have the magic to understand all of the scenarios that I described, and it knows when to clean up your object, and if you really need code to run when the GC detects no references, you can use a finalizer). Be careful with finalizers, though -- they are only for unmanaged allocations that your class owns.
You can read more about this stuff here:
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
and here: http://www.bluebytesoftware.com/blog/2005/04/08/DGUpdateDisposeFinalizationAndResourceManagement.aspx
If you need unmanaged handle cleanup, read about SafeHandles as well.
It's not the responsibility of the compiler to interpret the scopes in your application and do things like figure out when you no longer need memory. In fact, I'm pretty sure that's an impossible problem to solve, because there's no way for the compiler to know what your program will look like at runtime, no matter how smart it is.
This is why we have the garbage collection. The problem with garbage collection is that it runs on an indeterminate interval, and typically if an object implements IDisposable, the reason is because you want the ability to dispose of it immediately. Like, right now immediately. Constructs such as database connections aren't just disposable because they have some special work to do when they get trashed - it's also because they are scarce.
I seems difficult for the G.C. to know that you won't be using this variable anymore later in the same method. Obviously, if you leave the method, and don't keep a further reference to you variable, the G.C. will dispose it. But using using in you sample, tells the G.C. that you are sure that you will not be using this variable anymore after.
The using statement has nothing to do with performance (unless you consider avoiding resource/memory leaks as performance).
All it does for you is guarantee that the IDisposable.Dispose method is called on the object in question when it goes out of scope, even if an exception has occurred inside the using block.
The Dispose() method is then responsible for releasing any resources used by the object. These are most often unmanaged resources such as files, fonts, images etc, but could also be simple "clean-up" activities on managed objects (not garbage collection however).
Of course if the Dispose() method is implemented badly, the using statement provides zero benefit.
I think the OP is saying "why bother with 'using' when the compiler should be able to work it out magically pretty easily".
I think the OP is saying that
public void SomeMethod()
{
...
var foo = new Foo();
... do stuff with Foo ...
// Foo isn't use after here (obviously).
...
}
should be equivalent to
public void SomeMethod()
{
...
using (var foo = new Foo())
{
... do stuff with Foo ...
}
// Foo isn't use after here (obviously).
...
}
because Foo isn't used again.
The answer of course is that the compiler cannot work it out pretty easily. Garbage Collection (what magically calls "Dispose()" in .NET) is a very complicated field. Just because the symbol isn't being used below that doesn't mean that the variable isn't being used.
Take this example:
public void SomeMethod()
{
...
var foo = new Foo();
foo.DoStuffWith(someRandomObject);
someOtherClass.Method(foo);
// Foo isn't use after here (obviously).
// Or is it??
...
}
In this example, someRandomObject and someOtherClass might both have references to what Foo points out, so if we called Foo.Dispose() it would break them. You say you're just imagining the simple case, but the only 'simple case' where what you're proposing works is the case where you make no method calls from Foo and do not pass Foo or any of its members to anything else - effectively when you don't even use Foo at all in which case you probably have no need to declare it. Even then, you can never be sure that some kind of reflection or event hackery didn't get a reference to Foo just by its very creation, or that Foo didn't hook itself up with something else during its constructor.
In addition to the fine reasons listed above, since the problem can't be solved reliably for all cases, those "easy" cases are something that code analysis tools can and do detect. Let the compiler do stuff deterministically, and let your automatic code analysis tools tell you when you're doing something silly like forgetting to call Dispose.
Do you need to dispose of objects and set them to null, or will the garbage collector clean them up when they go out of scope?
Objects will be cleaned up when they are no longer being used and when the garbage collector sees fit. Sometimes, you may need to set an object to null in order to make it go out of scope (such as a static field whose value you no longer need), but overall there is usually no need to set to null.
Regarding disposing objects, I agree with #Andre. If the object is IDisposable it is a good idea to dispose it when you no longer need it, especially if the object uses unmanaged resources. Not disposing unmanaged resources will lead to memory leaks.
You can use the using statement to automatically dispose an object once your program leaves the scope of the using statement.
using (MyIDisposableObject obj = new MyIDisposableObject())
{
// use the object here
} // the object is disposed here
Which is functionally equivalent to:
MyIDisposableObject obj;
try
{
obj = new MyIDisposableObject();
}
finally
{
if (obj != null)
{
((IDisposable)obj).Dispose();
}
}
Objects never go out of scope in C# as they do in C++. They are dealt with by the Garbage Collector automatically when they are not used anymore. This is a more complicated approach than C++ where the scope of a variable is entirely deterministic. CLR garbage collector actively goes through all objects that have been created and works out if they are being used.
An object can go "out of scope" in one function but if its value is returned, then GC would look at whether or not the calling function holds onto the return value.
Setting object references to null is unnecessary as garbage collection works by working out which objects are being referenced by other objects.
In practice, you don't have to worry about destruction, it just works and it's great :)
Dispose must be called on all objects that implement IDisposable when you are finished working with them. Normally you would use a using block with those objects like so:
using (var ms = new MemoryStream()) {
//...
}
EDIT On variable scope. Craig has asked whether the variable scope has any effect on the object lifetime. To properly explain that aspect of CLR, I'll need to explain a few concepts from C++ and C#.
Actual variable scope
In both languages the variable can only be used in the same scope as it was defined - class, function or a statement block enclosed by braces. The subtle difference, however, is that in C#, variables cannot be redefined in a nested block.
In C++, this is perfectly legal:
int iVal = 8;
//iVal == 8
if (iVal == 8){
int iVal = 5;
//iVal == 5
}
//iVal == 8
In C#, however you get a a compiler error:
int iVal = 8;
if(iVal == 8) {
int iVal = 5; //error CS0136: A local variable named 'iVal' cannot be declared in this scope because it would give a different meaning to 'iVal', which is already used in a 'parent or current' scope to denote something else
}
This makes sense if you look at generated MSIL - all the variables used by the function are defined at the start of the function. Take a look at this function:
public static void Scope() {
int iVal = 8;
if(iVal == 8) {
int iVal2 = 5;
}
}
Below is the generated IL. Note that iVal2, which is defined inside the if block is actually defined at function level. Effectively this means that C# only has class and function level scope as far as variable lifetime is concerned.
.method public hidebysig static void Scope() cil managed
{
// Code size 19 (0x13)
.maxstack 2
.locals init ([0] int32 iVal,
[1] int32 iVal2,
[2] bool CS$4$0000)
//Function IL - omitted
} // end of method Test2::Scope
C++ scope and object lifetime
Whenever a C++ variable, allocated on the stack, goes out of scope it gets destructed. Remember that in C++ you can create objects on the stack or on the heap. When you create them on the stack, once execution leaves the scope, they get popped off the stack and gets destroyed.
if (true) {
MyClass stackObj; //created on the stack
MyClass heapObj = new MyClass(); //created on the heap
obj.doSomething();
} //<-- stackObj is destroyed
//heapObj still lives
When C++ objects are created on the heap, they must be explicitly destroyed, otherwise it is a memory leak. No such problem with stack variables though.
C# Object Lifetime
In CLR, objects (i.e. reference types) are always created on the managed heap. This is further reinforced by object creation syntax. Consider this code snippet.
MyClass stackObj;
In C++ this would create an instance on MyClass on the stack and call its default constructor. In C# it would create a reference to class MyClass that doesn't point to anything. The only way to create an instance of a class is by using new operator:
MyClass stackObj = new MyClass();
In a way, C# objects are a lot like objects that are created using new syntax in C++ - they are created on the heap but unlike C++ objects, they are managed by the runtime, so you don't have to worry about destructing them.
Since the objects are always on the heap the fact that object references (i.e. pointers) go out of scope becomes moot. There are more factors involved in determining if an object is to be collected than simply presence of references to the object.
C# Object references
Jon Skeet compared object references in Java to pieces of string that are attached to the balloon, which is the object. Same analogy applies to C# object references. They simply point to a location of the heap that contains the object. Thus, setting it to null has no immediate effect on the object lifetime, the balloon continues to exist, until the GC "pops" it.
Continuing down the balloon analogy, it would seem logical that once the balloon has no strings attached to it, it can be destroyed. In fact this is exactly how reference counted objects work in non-managed languages. Except this approach doesn't work for circular references very well. Imagine two balloons that are attached together by a string but neither balloon has a string to anything else. Under simple ref counting rules, they both continue to exist, even though the whole balloon group is "orphaned".
.NET objects are a lot like helium balloons under a roof. When the roof opens (GC runs) - the unused balloons float away, even though there might be groups of balloons that are tethered together.
.NET GC uses a combination of generational GC and mark and sweep. Generational approach involves the runtime favouring to inspect objects that have been allocated most recently, as they are more likely to be unused and mark and sweep involves runtime going through the whole object graph and working out if there are object groups that are unused. This adequately deals with circular dependency problem.
Also, .NET GC runs on another thread(so called finalizer thread) as it has quite a bit to do and doing that on the main thread would interrupt your program.
As others have said you definitely want to call Dispose if the class implements IDisposable. I take a fairly rigid position on this. Some might claim that calling Dispose on DataSet, for example, is pointless because they disassembled it and saw that it did not do anything meaningful. But, I think there are fallacies abound in that argument.
Read this for an interesting debate by respected individuals on the subject. Then read my reasoning here why I think Jeffery Richter is in the wrong camp.
Now, on to whether or not you should set a reference to null. The answer is no. Let me illustrate my point with the following code.
public static void Main()
{
Object a = new Object();
Console.WriteLine("object created");
DoSomething(a);
Console.WriteLine("object used");
a = null;
Console.WriteLine("reference set to null");
}
So when do you think the object referenced by a is eligible for collection? If you said after the call to a = null then you are wrong. If you said after the Main method completes then you are also wrong. The correct answer is that it is eligible for collection sometime during the call to DoSomething. That is right. It is eligible before the reference is set to null and perhaps even before the call to DoSomething completes. That is because the JIT compiler can recognize when object references are no longer dereferenced even if they are still rooted.
You never need to set objects to null in C#. The compiler and runtime will take care of figuring out when they are no longer in scope.
Yes, you should dispose of objects that implement IDisposable.
If the object implements IDisposable, then yes, you should dispose it. The object could be hanging on to native resources (file handles, OS objects) that might not be freed immediately otherwise. This can lead to resource starvation, file-locking issues, and other subtle bugs that could otherwise be avoided.
See also Implementing a Dispose Method on MSDN.
I agree with the common answer here that yes you should dispose and no you generally shouldn't set the variable to null... but I wanted to point out that dispose is NOT primarily about memory management. Yes, it can help (and sometimes does) with memory management, but it's primary purpose is to give you deterministic releasing of scarce resources.
For example, if you open a hardware port (serial for example), a TCP/IP socket, a file (in exclusive access mode) or even a database connection you have now prevented any other code from using those items until they are released. Dispose generally releases these items (along with GDI and other "os" handles etc. which there are 1000's of available, but are still limited overall). If you don't call dipose on the owner object and explicitly release these resources, then try to open the same resource again in the future (or another program does) that open attempt will fail because your undisposed, uncollected object still has the item open. Of course, when the GC collects the item (if the Dispose pattern has been implemented correctly) the resource will get released... but you don't know when that will be, so you don't know when it's safe to re-open that resource. This is the primary issue Dispose works around. Of course, releasing these handles often releases memory too, and never releasing them may never release that memory... hence all the talk about memory leaks, or delays in memory clean up.
I have seen real world examples of this causing problems. For instance, I have seen ASP.Net web applications that eventually fail to connect to the database (albeit for short periods of time, or until the web server process is restarted) because the sql server 'connection pool is full'... i.e, so many connections have been created and not explicitly released in so short a period of time that no new connections can be created and many of the connections in the pool, although not active, are still referenced by undiposed and uncollected objects and so can't be reused. Correctly disposing the database connections where necessary ensures this problem doesn't happen (at least not unless you have very high concurrent access).
If they implement the IDisposable interface then you should dispose them. The garbage collector will take care of the rest.
EDIT: best is to use the using command when working with disposable items:
using(var con = new SqlConnection("..")){ ...
Always call dispose. It is not worth the risk. Big managed enterprise applications should be treated with respect. No assumptions can be made or else it will come back to bite you.
Don't listen to leppie.
A lot of objects don't actually implement IDisposable, so you don't have to worry about them. If they genuinely go out of scope they will be freed automatically. Also I have never come across the situation where I have had to set something to null.
One thing that can happen is that a lot of objects can be held open. This can greatly increase the memory usage of your application. Sometimes it is hard to work out whether this is actually a memory leak, or whether your application is just doing a lot of stuff.
Memory profile tools can help with things like that, but it can be tricky.
In addition always unsubscribe from events that are not needed. Also be careful with WPF binding and controls. Not a usual situation, but I came across a situation where I had a WPF control that was being bound to an underlying object. The underlying object was large and took up a large amount of memory. The WPF control was being replaced with a new instance, and the old one was still hanging around for some reason. This caused a large memory leak.
In hindsite the code was poorly written, but the point is that you want to make sure that things that are not used go out of scope. That one took a long time to find with a memory profiler as it is hard to know what stuff in memory is valid, and what shouldn't be there.
When an object implements IDisposable you should call Dispose (or Close, in some cases, that will call Dispose for you).
You normally do not have to set objects to null, because the GC will know that an object will not be used anymore.
There is one exception when I set objects to null. When I retrieve a lot of objects (from the database) that I need to work on, and store them in a collection (or array). When the "work" is done, I set the object to null, because the GC does not know I'm finished working with it.
Example:
using (var db = GetDatabase()) {
// Retrieves array of keys
var keys = db.GetRecords(mySelection);
for(int i = 0; i < keys.Length; i++) {
var record = db.GetRecord(keys[i]);
record.DoWork();
keys[i] = null; // GC can dispose of key now
// The record had gone out of scope automatically,
// and does not need any special treatment
}
} // end using => db.Dispose is called
Normally, there's no need to set fields to null. I'd always recommend disposing unmanaged resources however.
From experience I'd also advise you to do the following:
Unsubscribe from events if you no longer need them.
Set any field holding a delegate or an expression to null if it's no longer needed.
I've come across some very hard to find issues that were the direct result of not following the advice above.
A good place to do this is in Dispose(), but sooner is usually better.
In general, if a reference exists to an object the garbage collector (GC) may take a couple of generations longer to figure out that an object is no longer in use. All the while the object remains in memory.
That may not be a problem until you find that your app is using a lot more memory than you'd expect. When that happens, hook up a memory profiler to see what objects are not being cleaned up. Setting fields referencing other objects to null and clearing collections on disposal can really help the GC figure out what objects it can remove from memory. The GC will reclaim the used memory faster making your app a lot less memory hungry and faster.
I have to answer, too.
The JIT generates tables together with the code from it's static analysis of variable usage.
Those table entries are the "GC-Roots" in the current stack frame. As the instruction pointer advances, those table entries become invalid and so ready for garbage collection.
Therefore: If it is a scoped variable, you don't need to set it to null - the GC will collect the object.
If it is a member or a static variable, you have to set it to null
A little late to the party, but there is one scenario that I don't think has been mentioned here - if class A implements IDisposable, and exposes public properties that are also IDisposable objects, then I think it's good practice for class A not only to dispose of the disposable objects that it has created in its Dispose method, but also to set them to null. The reason for this is that disposing an object and letting it get GCed (because there are no more references to it) are by no means the same thing, although it is pretty definitely a bug if it happens. If a client of Class A does dispose its object of type ClassA, the object still exists. If the client then tries to access one of these public properties (which have also now been disposed) the results can be quite unexpected. If they have been nulled as well as disposed, there will be a null reference exception immediately, which will make the problem easier to diagnose.