Compartir a través de


Implementing Using from simpler parts.

Using is a very convenient language element. When I have to write something that should be compilable by older version of the compiler, "Using" is one of the new features that I really miss. Here is an example how to achieve the same behavior without Using:

Sub

foo1()
Using f As New IO.StreamWriter("somefile.txt")
f.WriteLine("hello")
End Using
End Sub

Sub foo2()
Dim f As New IO.StreamWriter("somefile.txt")
Try
f.WriteLine("hello")
Finally
'assume that the code inside Try may assign Nothing to f,
'but in most cases check for Nothing is not necessary
If f IsNot Nothing Then f.Dispose()
End Try

End Sub

If you compile functions above and check IL code produced you will find that it is identical:

.method public static void foo1() cil managed // foo2 is identical
{
// Code size 35 (0x23)
.maxstack 2
.locals init ([0] class [mscorlib]System.IO.StreamWriter f)
IL_0000: ldstr "somefile.txt"
IL_0005: newobj instance void [mscorlib]System.IO.StreamWriter::.ctor(string)
IL_000a: stloc.0
.try
{
IL_000b: ldloc.0
IL_000c: ldstr "hello"
IL_0011: callvirt instance void [mscorlib]System.IO.TextWriter::WriteLine(string)
IL_0016: leave.s IL_0022
} // end .try
finally
{
IL_0018: ldloc.0
IL_0019: brfalse.s IL_0021
IL_001b: ldloc.0
IL_001c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0021: endfinally
} // end handler
IL_0022: ret
} // end of method Module1::foo1

On this simple level it seems clear how Using works and the feature itself seems faily simple - just syntactical sugar for a Try/Finally block. However all the convenience of Using is appreciated when you have to nest Using or use several Using blocks in the same method. Suddenly Using is a clear winner over the Try/Finally implementation in terms of lines of code, better scoping and readability.

 

Just compare these two methods (they do the same thing): 

Sub foo3()
Using reader As New IO.StreamReader("f1.txt"), writer As New IO.StreamWriter("f2.txt")
writer.WriteLine(reader.ReadLine)
End Using
End Sub

Sub foo4()
Dim reader As New IO.StreamReader("f1.txt")
Try
Dim writer As New IO.StreamWriter("f2.txt")
Try
writer.WriteLine(reader.ReadLine)
Finally
If writer IsNot Nothing Then writer.Dispose()
End Try
Finally
If reader IsNot Nothing Then reader.Dispose()
End Try
End Sub