我有以下简单的C#代码:
private Stack<Person> m_stack = new Stack<Person>();
public void Add<T>(T obj)
where T : Person
{
m_stack.Push(obj);
}
Run Code Online (Sandbox Code Playgroud)
这将产生以下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`1<class ConsoleApplication1.Person> ConsoleApplication1.Pool::m_stack
IL_0007: ldarg.1
IL_0008: box !!T
IL_000d: callvirt instance void class [System]System.Collections.Generic.Stack`1<class ConsoleApplication1.Person>::Push(!0)
IL_0012: nop
IL_0013: ret
} // end of method Pool::Add
Run Code Online (Sandbox Code Playgroud)
所以我的问题是......为什么拳击?(IL_0008)我可以理解向下转换甚至编译错误,但为什么拳击(Person是引用类型...)
提前致谢!
rui*_*yiz 31
摘自Ecma-335 Partition III 4.1
如果typeTok是引用类型,则box指令不执行任何操作.
在你的情况下,typeTok是!! T.
我的猜测是,当编译器编译代码时,无论操作数的类型是否为引用类型,它总是调用box.由于box指令的语义,始终保证期望的结果.
我相信这是通用方法约束对您执行此操作 - 但是......
无论如何,根本不需要通用方法。只需将其写为:
public void Add(Person person)
{
m_stack.Push(person);
}
Run Code Online (Sandbox Code Playgroud)
您会发现 IL 得到了简化,并且完全避免了该问题。如果您限制特定的引用类型,则可以仅使用该引用类型。
这更容易理解,也更清晰。我建议避免通用方法调用,除非确实需要。泛型方法使类不那么明显,这意味着从长远来看可读性和可维护性较差,并且更难以使用。
| 归档时间: |
|
| 查看次数: |
1642 次 |
| 最近记录: |