本文介绍了处置和.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);
        }

实际上会发生在后一张code是什么?会的Dispose()被调用?

What will actually happen in the latter piece of code? Will the Dispose() be called?

推荐答案

using语句的资源,读者将使用范围结束时进行处理。在你的情况下反序列化之后的结果已经铸造至T这就是。

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.

您可以扩展你code到(约)相当于如下:

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();
}

在该版本中它变得清晰,最后一次阅读器采用的是return语句之前的方式。

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.

编辑:上述code的IL是:

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

要注意的一点是,CS $ 1 $ 0000这是返回值是推到堆栈只是唯一的ret指令之前。因此,执行的顺序是什么样子的C#code不同。另外值得注意的stloc.s CS $ 1 $ 0000 leave.s instrcutions存储返回值其次是荣耀的GOTO语句之一。 leave.s离开try并跳转到标签IL_003d,只需按下返回值堆栈

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

这篇关于处置和.NET返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 21:24