The resource of the using statement, reader will be disposed when the using scope ends. In you're case that's when the result of the deserialization has been casted to T.
you could extend you're code to the (roughly) equivalent below:
TextReader reader = null;
try{
reader = new StreamReader(file);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
var obj = xmlSerializer.Deserialize(reader);
T returnVal = (T)obj;
return returnVal;
} finally{
reader.Dispose();
}
in that version it becomes clear that the last time reader is used is way before the return statement.
If you were to return reader you would run into problems since the object returned would be disposed and hence unusable.
EDIT:
The IL of the above code is:
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.0
.try
{
IL_0003: nop
IL_0004: ldstr ""
IL_0009: newobj instance void [mscorlib]System.IO.StreamReader::.ctor(string)
IL_000e: stloc.0
IL_000f: ldtoken !!T
IL_0014: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0019: newobj instance void [System.Xml]System.Xml.Serialization.XmlSerializer::.ctor(class [mscorlib]System.Type)
IL_001e: stloc.1
IL_001f: ldloc.1
IL_0020: ldloc.0
IL_0021: callvirt instance object [System.Xml]System.Xml.Serialization.XmlSerializer::Deserialize(class [mscorlib]System.IO.TextReader)
IL_0026: stloc.2
IL_0027: ldloc.2
IL_0028: unbox.any !!T
IL_002d: stloc.3
IL_002e: ldloc.3
IL_002f: stloc.s CS$1$0000
IL_0031: leave.s IL_003d
} // end .try
finally
{
IL_0033: nop
IL_0034: ldloc.0
IL_0035: callvirt instance void [mscorlib]System.IO.TextReader::Dispose()
IL_003a: nop
IL_003b: nop
IL_003c: endfinally
} // end handler
IL_003d: nop
IL_003e: ldloc.s CS$1$0000
IL_0040: ret
} // end of method
the thing to notice is that CS$1$0000 which is the return value is push to the stack just before the only ret instruction. So the order of execution is different from what it looks like in C# code. Further it's worth noting the stloc.s CS$1$0000 and leave.s instrcutions which stores the return value followed by one of the glorified GOTOs. leave.s leaves the try and jumps to the label IL_003d, just before pushing the return value to the stack