When we write inside the using block the compiler coverts the code as try and finally block. This is the reason we don’t need to explicitly release or dispose the object, once it’s being used, as the object created gets disposed inside the finally block.
Please see the code snippet given below as well as the respective IL code for better understanding.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace ConsoleApplication1 {
- public class Program {
- static void Main(string[] args) {
- using(var obj = new CustomDbConnection()) {
-
- }
- }
- }
- }
Respective IL code
In the code given below, you can see the code given above within using interpreted as try, finally block and the dispose method gets called inside the finally.
Note
Within using, you can instantiate the objects of class, which implements IDisposable interface, so dispose method can be called.
- .method private hidebysig static void Main(string[] args) cil managed {.entrypoint
-
- .maxstack 2.locals init([0] class ConsoleApplication1.CustomDbConnection obj, [1] bool CS$4$0000)
- IL_0000: nop
- IL_0001: newobj instance void ConsoleApplication1.CustomDbConnection::.ctor()
- IL_0006: stloc .0.try {
- IL_0007: nop
- IL_0008: nop
- IL_0009: leave.s IL_001b
- }
- finally {
- IL_000b: ldloc .0
- IL_000c: ldnull
- IL_000d: ceq
- IL_000f: stloc .1
- IL_0010: ldloc .1
- IL_0011: brtrue.s IL_001a
- IL_0013: ldloc .0
- IL_0014: callvirt instance void[mscorlib] System.IDisposable::Dispose()
- IL_0019: nop
- IL_001a: endfinally
- }
- IL_001b: nop
- IL_001c: ret
- }
I believe, this helps us to understand what actually happens when we write the code inside the using block.