Do you need to dispose of objects and set them to null?
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();
}
}
Does setting an object to null dispose the object deterministically?
No, it will not.
do this:
public void Dispose()
{
// check if object has IDisposble implemented
IDisposable disposePricing = pricingEnvironment as IDisposable;
if (disposePricing!=null)
{
disposePricing.Dispose();
}
}
and have a read on this CLR Inside Out article from 2007
Setting an object to null vs Dispose()
It's important to separate disposal from garbage collection. They are completely separate things, with one point in common which I'll come to in a minute.
Dispose
, garbage collection and finalization
When you write a using
statement, it's simply syntactic sugar for a try/finally block so that Dispose
is called even if the code in the body of the using
statement throws an exception. It doesn't mean that the object is garbage collected at the end of the block.
Disposal is about unmanaged resources (non-memory resources). These could be UI handles, network connections, file handles etc. These are limited resources, so you generally want to release them as soon as you can. You should implement IDisposable
whenever your type "owns" an unmanaged resource, either directly (usually via an IntPtr
) or indirectly (e.g. via a Stream
, a SqlConnection
etc).
Garbage collection itself is only about memory - with one little twist. The garbage collector is able to find objects which can no longer be referenced, and free them. It doesn't look for garbage all the time though - only when it detects that it needs to (e.g. if one "generation" of the heap runs out of memory).
The twist is finalization. The garbage collector keeps a list of objects which are no longer reachable, but which have a finalizer (written as ~Foo()
in C#, somewhat confusingly - they're nothing like C++ destructors). It runs the finalizers on these objects, just in case they need to do extra cleanup before their memory is freed.
Finalizers are almost always used to clean up resources in the case where the user of the type has forgotten to dispose of it in an orderly manner. So if you open a FileStream
but forget to call Dispose
or Close
, the finalizer will eventually release the underlying file handle for you. In a well-written program, finalizers should almost never fire in my opinion.
Setting a variable to null
One small point on setting a variable to null
- this is almost never required for the sake of garbage collection. You might sometimes want to do it if it's a member variable, although in my experience it's rare for "part" of an object to no longer be needed. When it's a local variable, the JIT is usually smart enough (in release mode) to know when you're not going to use a reference again. For example:
StringBuilder sb = new StringBuilder();
sb.Append("Foo");
string x = sb.ToString();
// The string and StringBuilder are already eligible
// for garbage collection here!
int y = 10;
DoSomething(y);
// These aren't helping at all!
x = null;
sb = null;
// Assume that x and sb aren't used here
The one time where it may be worth setting a local variable to null
is when you're in a loop, and some branches of the loop need to use the variable but you know you've reached a point at which you don't. For example:
SomeObject foo = new SomeObject();
for (int i=0; i < 100000; i++)
{
if (i == 5)
{
foo.DoSomething();
// We're not going to need it again, but the JIT
// wouldn't spot that
foo = null;
}
else
{
// Some other code
}
}
Implementing IDisposable/finalizers
So, should your own types implement finalizers? Almost certainly not. If you only indirectly hold unmanaged resources (e.g. you've got a FileStream
as a member variable) then adding your own finalizer won't help: the stream will almost certainly be eligible for garbage collection when your object is, so you can just rely on FileStream
having a finalizer (if necessary - it may refer to something else, etc). If you want to hold an unmanaged resource "nearly" directly, SafeHandle
is your friend - it takes a bit of time to get going with, but it means you'll almost never need to write a finalizer again. You should usually only need a finalizer if you have a really direct handle on a resource (an IntPtr
) and you should look to move to SafeHandle
as soon as you can. (There are two links there - read both, ideally.)
Joe Duffy has a very long set of guidelines around finalizers and IDisposable (co-written with lots of smart folk) which are worth reading. It's worth being aware that if you seal your classes, it makes life a lot easier: the pattern of overriding Dispose
to call a new virtual Dispose(bool)
method etc is only relevant when your class is designed for inheritance.
This has been a bit of a ramble, but please ask for clarification where you'd like some :)
Why does this variable need to be set to null after the object is disposed?
It's not directly a PowerShell issue. When a using
block terminates, the specified object(s) have their Dispose()
methods called. These typically do some cleanup operations, often to avoid leaking memory and so forth. However, Dispose()
doesn't delete the object. If a reference to it still exists outside the using
block (as in this example), then the object itself is still in scope. It can't be garbage-collected because there's still a reference to it, so it's still taking up memory.
What they're doing in your example is dropping that reference. When powershell
is set to null, the PowerShell object it was pointing to is orphaned, since there are no other variables referring to it. Once the garbage collector figures that out, it can free up the memory. This would happen at the end of the method anyway (because powershell
would go out of scope), but this way you get the system resources back a little sooner.
(Edit: As Brian Rasmussen points out, the .NET runtime is extremely clever about garbage collection. Once it reaches the last reference to powershell
in your code, the runtime should detect that you don't need it anymore and release it for garbage collection. So the powershell = null;
line isn't actually doing anything.)
By the way, this pattern looks very strange to me. The usual approach is something like this:
using (PowerShell powershell = PowerShell.Create())
{
//...
}
This way, powershell
goes out of scope at the end of the using
block, right after it's disposed. It's easier to tell where the variable is relevant, and you save some code because you don't need the powershell = null
line anymore. I'd even say this is better coding practice, because powershell
never exists in an already-disposed state. If someone modifies your original code and tries to use powershell
outside the using
block, whatever happens will probably be bad.
Do I need to check if the object is null before a dispose() command?
It's generally recommend to wrap anything which implements IDisposable
with the using statement
using (var a = new HttpWebResponse(...))
{
}
It's the equivalent of writing
var a = new HttpWebResponse(...);
try
{
// use a
}
finally
{
if (a != null)
a.Dispose();
}
Should I even care if the object is null? Can't I just Dispose of it anyway
Well no, because if you attempt to call Dispose
on a null
object the application will throw a NullReferenceException
. Given your circumstance where you feel the using
statement isn't a valid option another neat of way tidying this up is to write an extension method e.g.
public static class Ext
{
public static void SafeDispose(this object obj)
{
if (obj != null)
obj.Dispose();
}
}
...
var a = new ...;
a.SafeDispose();
This then would allow you to call the method on a null object.
To dispose an object should I set all properties to null?
Implementing IDisposable
doesn't mean that you've to set all the fields to null
. GC will take care of that when they are not reachable from the root objects.
And setting null
will not do anything still the object will be in memory till GC notices it is not having managed any references.
IMO you can't see a comprehensive answer more than this Proper use of the IDisposable interface
Setting null helps only when there is only one managed reference left, you don't need it though but you need to keep the encapsulating type alive then you'll set reference to null
. Otherwise if encapsulating type itself is not reachable then setting null
doesn't makes any sense.
Can I dispose multiple Objects in a single go?
You don't need to set the objects to null, and with C# 6 you can use the Null-Propagation syntax:
inst1?.Dispose();
inst2?.Dispose();
inst3?.Dispose();
This reduces the noise considerably.
Do we need to set object of custom class as null or GC will take care of it
TL;DR
You are missing a using
statement at the SqlReader
. The other scenrarions are handled by the GC. Always use Dispose
or using
if you are done with objects that implements the IDisposable
interface (there are a few exceptions on this last note).
note:
for a "subtitle" difference in lifetime and scope, see @Damien_The_Unbeliever's comment. For more info about the garbage collection see MSDN: https://msdn.microsoft.com/en-us/library/0xy59wtx(v=vs.110).aspx
In general, all managed objects which have no outstanding references, will be taken care of by the GC. So in general, you don't need to explicitly set them to null.
However, if a object implements the IDisposable
interface, it is preferred to call Dispose
when you are done with the object. Although (if correctly implemented), this will also be called during the Finalize
call, it's preferred to call Dispose
explicit (or through the using
statement). Objects, like database connections, graphic objects or network-connection can otherwise lead to a full connection pool or occupies graphic memory.
Be advised that this is all about scope and outstanding references.
if you have a method, like this, the object
"behind" database
will be taken care of as soon as it leaves the scope because no other variables are referring to this object:
public void Foo()
{
Database database = new Database();
string res = database.DoSomething();
//you don't need this call
// because the will be no outstanding references after the method exits.
//database = null;
}
But if the containing object is static or kept alive in another way, you'll get this scenario; the database
is kept alive as long as there is a valid reference somewhere to that FooClass
object:
public class FooClass
{
Database database = new Database();
public void Foo()
{
//some operation
}
}
If a member implements IDisposable
it is best to call it through a using
statement or explicitly (Dispose()
). Although the GC should handle this, especially with third party libraries, it requires for IDisposable
to be correctly implemented. If you see this example, you can see that it can be tricky and therefore is a suspect when facing memory leaks.
Proper use of the IDisposable interface
So, to answer your question's scenarios:
In the following, the using
statement, is equivalent to a try, catch finaly
block. See https://docs.microsoft.com/en-us/dotnet/articles/csharp/language-reference/keywords/using-statement
public class Database
{
public string DoSomething()
{
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("Select ID,Name From Person", con))
{
//note: using a using here as well
using (SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
//this is ok, because the USING will take care of the disposure.
return reader["Name"].ToString();
}
}
}
}
}
}
So far I think this is enough information to answer the question about the GC. There is one point of attention though; if you are facing unmanaged objects, there are other calls necessary for proper disposure. COM
for example requires Marshall.ReleaseComObject()
, and some libraries (some industrial camera drivers I know of), require an explicit, CleanUp
call.
Related Topics
Execute a Large SQL Script (With Go Commands)
Get Output Parameter Value in Ado.Net
Filling Missing Dates by Group
Why Do We Need Boxing and Unboxing in C#
Mock Httpcontext.Current in Test Init Method
Setting Authorization Header of Httpclient
Unit Testing Private Methods in C#
Setting a Property by Reflection With a String Value
How to Get Httpcontext.Current in ASP.NET Core
Why Response.Redirect Causes System.Threading.Threadabortexception
Asp.Net Identity'S Default Password Hasher - How Does It Work and Is It Secure
Which Parsers Are Available For Parsing C# Code
Reflection: How to Invoke Method With Parameters