不会发生装箱。
using
不是一个方法调用,它只是编译器将其转换为大致如下的语法糖:
MyClass m = new MyClass()
try
{
}
finally
{
if (m != null) {
m.Dispose();
}
}
它在声明中从不使用 IDisposable
,也从不将实例传递给其他任何东西。对于结构体,编译器实际上生成的内容更小:
MyStruct m = new MyStruct()
try
{
}
finally
{
m.Dispose();
}
由于结构体不能为null。
现在,为了确保它永远不会装箱,请查看IL。
尝试这个示例代码:
class StructBox
{
public static void Test()
{
using(MyStruct m = new MyStruct())
{
}
MyStruct m2 = new MyStruct();
DisposeSomething(m2);
}
public static void DisposeSomething(IDisposable disposable)
{
if (disposable != null)
{
disposable.Dispose();
}
}
private struct MyStruct : IDisposable
{
public void Dispose()
{
}
}
}
然后查看IL:
.method public hidebysig static void Test() cil managed
{
.maxstack 1
.locals init (
[0] valuetype ConsoleApplication1.StructBox/MyStruct m,
[1] valuetype ConsoleApplication1.StructBox/MyStruct m2)
L_0000: ldloca.s m
L_0002: initobj ConsoleApplication1.StructBox/MyStruct
L_0008: leave.s L_0018
L_000a: ldloca.s m
L_000c: constrained ConsoleApplication1.StructBox/MyStruct
L_0012: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_0017: endfinally
L_0018: ldloca.s m2
L_001a: initobj ConsoleApplication1.StructBox/MyStruct
L_0020: ldloc.1
L_0021: box ConsoleApplication1.StructBox/MyStruct
L_0026: call void ConsoleApplication1.StructBox::DisposeSomething(class [mscorlib]System.IDisposable)
L_002b: ret
.try L_0008 to L_000a finally handler L_000a to L_0018
}
代码行 L_0000 到 L_0017 代表了 m
的声明和 using
。这里没有装箱。
代码行 L_0018 到 L_0026 代表了 m2
的声明和对 DisposeSomething
的调用。请参见第 L_0021 行的 box
。