在.NET中处理和返回值

考虑以下:

TextReader reader = new StreamReader(file); XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); return (T)xmlSerializer.Deserialize(reader); 

  using (TextReader reader = new StreamReader(file)) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); return (T)xmlSerializer.Deserialize(reader); } 

在后一段代码中会发生什么? 是否会调用Dispose()?

当使用范围结束时,将使用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(); } 

在那个版本中,很明显最后一次使用reader是在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#代码中的顺序不同。 此外,值得注意的是stloc.s CS $ 1 $ 0000和leave.s instrcutions,它们存储了返回值,然后是其中一个荣耀的GOTO。 leave.s离开try并跳转到标签IL_003d,就在将返回值推送到堆栈之前

是的,它会被调用。

using语句是语法糖:

 try { // Do stuff return; } finally { // Dispose } 

并且即使在return也会被调用。

所以你可以安全地使用它。

是的,将调用Dispose

是的,这是它在IL中的转换方式。

  TextReader reader; T returnValue; try{ reader = new StreamReader(file)); XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); var obj = xmlSerializer.Deserialize(reader); returnVal = (T)obj; } finally{ reader.Dispose(); return returnVal; }