c# – 在“使用……”的块中是否也处理了struct类型的深层副本?
假设我有一个实现IDisposible的结构类型,如果我使用下面的代码:
using (MyStruct ms = new MyStruct()) { InnerAction(ms); //Notice "InnerAction" is "InnerAction(MyStruct ms)" } 当然我看到在使用块之后,ms被处理掉了.然而,“InnerAction”中的结构呢?它是否仍然存在,因为深层复制或它也处置? 如果它仍然存活(未处理),我必须使用“ref”作为“InnerAction”吗? 请给我你的证明:) 大家好. 解决方法
它比你想象的更糟糕:ms甚至没有处理掉.
原因是using语句创建了一个内部副本,它在try / finally构造中调用dispose. 考虑一下这个LinqPad example: void Main() { MyStruct ms; using (ms = new MyStruct()) { InnerAction(ms); } ms.IsDisposed.Dump(); _naughtyCachedStruct.IsDisposed.Dump(); } MyStruct _naughtyCachedStruct; void InnerAction(MyStruct s) { _naughtyCachedStruct = s; } struct MyStruct : IDisposable { public Boolean IsDisposed { get; set; } public void Dispose() { IsDisposed = true; } } 这是一些反编译的IL: IL_0000: nop IL_0001: ldloca.s 01 // CS$0$0000 IL_0003: initobj UserQuery.MyStruct IL_0009: ldloc.1 // CS$0$0000 IL_000A: dup IL_000B: stloc.0 // ms IL_000C: dup IL_000D: stloc.0 // ms IL_000E: stloc.2 // CS$3$0001 IL_000F: nop IL_0010: ldarg.0 IL_0011: ldloc.0 // ms 请注意,在IL_000E中,创建了一个编译器生成的本地(CS $3 $0001),并在那里存储了ms的副本.后来… IL_001B: ldloca.s 02 // CS$3$0001 IL_001D: constrained. UserQuery.MyStruct IL_0023: callvirt System.IDisposable.Dispose IL_0028: nop IL_0029: endfinally 对此本地调用Dispose,而不是ms(存储在位置0中). 结果是ms和InnerAction所持有的副本都没有被处理掉. 结论:不要在using语句中使用结构. 编辑:正如@Weston在评论中指出的那样,you can manually box the struct and act on the boxed instance,因为它然后生活在堆上.这样你就可以获得要处置的实例,但是如果你把它强制转换回using语句中的struct,那么你只会在放置实例之前存储一个副本.此外,拳击移除了远离堆的好处,你可能在这里. MyStruct ms = new MyStruct(); var disposable = (IDisposable)ms; using (disposable) { InnerAction(disposable); } ((MyStruct)disposable).IsDisposed.Dump(); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |