Back to Basic: C# Using statement, Return and IDisposable
In day to day coding, I found myself using a lot of disposable objects like DbConnection, Font, etc. And so, naturally, putting this code block inside a using statement is common sense.
In theory, I know that when you use a using block in your code, your code is guaranteed to be disposed without having to do it manually.
But sometimes I doubt myself with question like "if I return something inside the using block, will my object be disposed properly?"
To alleviate my doubt I decided to do a little experiment. The code is as follow:
1: using System;
2:
3: namespace ConsoleApplication1
4: { 5: class Program
6: { 7: static void Main(string[] args)
8: { 9: Console.WriteLine(GetBar());
10: Console.ReadKey();
11: }
12:
13: static string GetBar()
14: { 15: using (Foo foo = new Foo())
16: { 17: Console.WriteLine("In Using..."); 18: return foo.Bar();
19: }
20: }
21: }
22:
23: class Foo : IDisposable
24: { 25: private bool disposed = false;
26:
27: public void Dispose()
28: { 29: Dispose(true);
30: GC.SuppressFinalize(this);
31: }
32:
33: protected virtual void Dispose(bool disposing)
34: { 35: if (!disposed)
36: { 37: if (disposing)
38: { 39: Console.WriteLine("Disposing"); 40: }
41: disposed = true;
42: }
43: }
44:
45: public string Bar()
46: { 47: return "Hello, World!";
48: }
49: }
50: }
As you can see, line 9 is calling the GetBar method (line 13-20) which has a using block and inside the block I return something from my sample disposable object Foo (Line 23-49).
I also added some tracing line in the example (Line 9, 17, and 39). To see if the assumption is correct.
After running the code the console displayed the following:
In Using...
Disposing
Hello, World!
Well, I guess that proved the assumption. I can be sure that my code will work as intended now. Happy, Happy, Joy, Joy!
If you are curious about Dispose pattern, there is an Implementing IDisposable and the Dispose Pattern Properly article in Code Project by Scott Dorman that you should read. It gives a much deeper insight on this stuff.
Apparently, the compiler will translate the using block (line 15-19) to something like:
1: Foo foo = new Foo();
2:
3: try
4: { 5: return foo.Bar();
6: }
7: finally
8: { 9: if (foo != null)
10: { 11: IDisposable disposable = foo;
12: disposable.Dispose();
13: }
14: }
Hmm... so... if I have a try finally block and I return something from inside the try block.... Nevermind... We already know that finally will be called no matter what... or is it?