在.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; }
是的,请看这里: –
http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx