The Dispose()
does not release variables, it frees resources.
Objects in memory (not to be confused with resources) are only released by Garbage Collector at a time when it’s up to him. Variables "are released" when the object containing it is released, or if it is local it is at the time it terminates its scope. Learn more about scope and time and life.
Each using
will call the Dispose()
only of the resource he created, nothing else. So it is necessary, but can do simply.
Depending on the use it is possible to simplify this code by placing everything in a single block, in this case just do:
using (var QDR = new DAL.teste())
using (var QDR1 = new DAL.teste1())
using (var QDR2 = new DAL.teste2()) {
// etc
}
I changed my class (MemoryStream
) just to make it easier and I had the IL generated just to get a sense of what this does:
.class public auto ansi beforefieldinit C
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig
instance void M () cil managed
{
// Method begins at RVA 0x2050
// Code size 61 (0x3d)
.maxstack 1
.locals init (
[0] class [mscorlib]System.IO.MemoryStream,
[1] class [mscorlib]System.IO.MemoryStream,
[2] class [mscorlib]System.IO.MemoryStream
)
IL_0000: nop
IL_0001: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
IL_0006: stloc.0
IL_0007: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
IL_000c: stloc.1
IL_000d: newobj instance void [mscorlib]System.IO.MemoryStream::.ctor()
IL_0012: stloc.2
IL_0013: nop
IL_0014: nop
IL_0015: leave.s IL_0022
IL_0017: ldloc.2
IL_0018: brfalse.s IL_0021
IL_001a: ldloc.2
IL_001b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0020: nop
IL_0021: endfinally
IL_0022: leave.s IL_002f
IL_0024: ldloc.1
IL_0025: brfalse.s IL_002e
IL_0027: ldloc.1
IL_0028: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_002d: nop
IL_002e: endfinally
IL_002f: leave.s IL_003c
IL_0031: ldloc.0
IL_0032: brfalse.s IL_003b
IL_0034: ldloc.0
IL_0035: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003a: nop
IL_003b: endfinally
IL_003c: ret
Try IL_0013-IL_0017 Finally IL_0017-IL_0022
Try IL_000d-IL_0024 Finally IL_0024-IL_002f
Try IL_0007-IL_0031 Finally IL_0031-IL_003c
} // end of method C::M
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20c4
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method C::.ctor
} // end of class C
Even in C# 8 this is not even necessary, the block has become optional (you can still use it if necessary or think it looks better, I think it does not, but who got used to it...):
using var QDR = new DAL.teste();
using var QDR1 = new DAL.teste1();
using var QDR2 = new DAL.teste2();
I put in the Github for future reference.
The block in which these three variables were declared will determine the end and where the release of the resource will take place.
in case my code would not give to group, but still worth a using for each? it would not release the resources already in the first using? since he is within him?
– Dorathoto
I don’t see why I couldn’t, but I can’t just talk through this. I can only repeat what is already in the answer, each releases only the resource he created, nothing else. There is this of being inside.
– Maniero