當使用範圍結束時,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,就在將返回值推入堆棧之前
是處置將被調用。 –