当使用范围结束时,using语句的资源将被放置。在你的情况下,当反序列化的结果已经被浇铸到T
这
可以扩展你的代码为(大约)以下等价的:在该版本
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();
}
它变得清晰使用最后一次阅读器是在return语句之前。
如果你要返回读者,你会遇到问题,因为返回的对象将被丢弃,因此无法使用。
编辑: 上面的代码中的IL是:
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
要注意的事情是,CS $ 1 $ 0000是返回值正好是唯一ret指令前推到堆栈中。所以执行顺序与C#代码中的不同。此外,值得注意的是,CSl $ 1 $ 0000和leave.sinstrcutions存储的返回值之一,其中一个荣耀的GOTO。 leave.s离开try并跳转到标签IL_003d,就在将返回值推入堆栈之前
是处置将被调用。 –