Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - Are objects immediately destroyed when going out of scope?

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.

like image 705
sharkin Avatar asked Sep 26 '09 09:09

sharkin


4 Answers

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.    }
like image 78
Peter Lillevold Avatar answered Oct 05 '22 06:10

Peter Lillevold


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()

like image 42
AgentConundrum Avatar answered Oct 05 '22 06:10

AgentConundrum


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.

like image 29
Joren Avatar answered Oct 05 '22 07:10

Joren


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().

like image 39
Joey Avatar answered Oct 05 '22 07:10

Joey