我有以下简单的C#代码:
private Stackm_stack = new Stack (); public void Add (T obj) where T : Person { m_stack.Push(obj); }
这将产生以下IL代码:
.method public hidebysig instance void Add<(ConsoleApplication1.Person) T>(!!T obj) cil managed { // Code size 20 (0x14) .maxstack 8 IL_0000: nop IL_0001: ldarg.0 IL_0002: ldfld class [System]System.Collections.Generic.Stack`1ConsoleApplication1.Pool::m_stack IL_0007: ldarg.1 IL_0008: box !!T IL_000d: callvirt instance void class [System]System.Collections.Generic.Stack`1 ::Push(!0) IL_0012: nop IL_0013: ret } // end of method Pool::Add
所以我的问题是......为什么拳击?(IL_0008)我可以理解向下转换甚至编译错误,但为什么拳击(Person是引用类型...)
提前致谢!
摘自Ecma-335 Partition III 4.1
如果typeTok是引用类型,则box指令不执行任何操作.
在你的情况下,typeTok是!! T.
我的猜测是,当编译器编译代码时,无论操作数的类型是否为引用类型,它总是调用box.由于box指令的语义,始终保证期望的结果.