This is worse than you think: ms is not even reclaimed.
The reason is that the using statement makes the internal copy that it invokes and removes the try / finally construct.
Consider this 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; } }
Here are some of the decompiled ILs:
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
Note that a compiler is created in IL_000E that is created locally ( CS$3$0001 ), and a copy of ms is stored there. Later...
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 is invoked against this local, not ms (which is stored at location 0).
The result is that both ms and the copy that InnerAction is holding InnerAction are both not located.
Conclusion : do not use structures in using statements.
EDIT: as @Weston points out in the comments, you can manually place the structure and act on the boxed instance as it is then on the heap. This way you can get the instance to be deleted, but if you returned it to the structure in the using statement, you only save the copy before the instance is deleted. In addition, boxing removes the benefit of turning off the heap, which you are probably still here.
MyStruct ms = new MyStruct(); var disposable = (IDisposable)ms; using (disposable) { InnerAction(disposable); } ((MyStruct)disposable).IsDisposed.Dump();