题
我刚刚参加堆栈溢出问题的 是一切都在.NET中对象?
和一张海报(在接受的答案的评论)似乎认为,执行上的值类型的方法调用导致了拳击。他指出我的 装箱和拆箱(C#编程指南) 的这不正是说明我们描述使用情况。
我不是一个信任的单一来源,所以我只是想获得关于这个问题的进一步反馈。我的直觉是,有没有拳击,但我的直觉不吸。 :d
要进一步阐述:
我使用的例子是:
int x = 5;
string s = x.ToString(); // Boxing??
这里接受的答案指出如果有问题的结构覆盖从对象继承该方法拳击确实不的发生。
然而,如果该结构没有覆盖的方法中,一个“限制” CIL 命令之前的callvirt被执行。根据该文件, 操作码。约束字段 ,<强>这导致拳击强>:
如果thisType是值类型和 thisType没有实现方法 然后PTR解除引用,盒装,和 因为“这个”指针传递 callvirt方法指令。
解决方案
这里的IL为您的代码:
L_0001: ldc.i4.5 // get a 5 on the stack
L_0002: stloc.0 // store into x
L_0003: ldloca.s x // get the address of x on the stack
L_0005: call instance string [mscorlib]System.Int32::ToString() // ToString
L_000a: stloc.1 // store in s
因此,在此情况下,答案是否定的。
其他提示
在的情况下,你已经给出的答案是否定的,因为底座指出。
然而,将如果调用的方法通过一个接口的指针。
考虑的代码:
interface IZot
{
int F();
}
struct Zot : IZot
{
public int F()
{
return 123;
}
}
然后
Zot z = new Zot();
z.F();
确实<强>不强>结果在拳击:
.locals init (
[0] valuetype ConsoleApplication1.Zot z)
L_0000: nop
L_0001: ldloca.s z
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloca.s z
L_000b: call instance int32 ConsoleApplication1.Zot::F()
L_0010: pop
L_0011: ret
然而,这确实:
IZot z = new Zot();
z.F();
.locals init (
[0] class ConsoleApplication1.IZot z,
[1] valuetype ConsoleApplication1.Zot CS$0$0000)
L_0000: nop
L_0001: ldloca.s CS$0$0000
L_0003: initobj ConsoleApplication1.Zot
L_0009: ldloc.1
L_000a: box ConsoleApplication1.Zot
L_000f: stloc.0
L_0010: ldloc.0
L_0011: callvirt instance int32 ConsoleApplication1.IZot::F()
L_0016: pop
@ ggf31316
“我相信调用toString, 等于和GetHashCode结果 拳击,如果结构不 覆盖的方法“。
我已经检查的ToString你。 INT32不重写的ToString,所以我做了一个结构是没有。我用 .net反射,以确保结构没有神奇地重写的ToString() ,并且它不是
因此,代码是这样的:
using System;
namespace ConsoleApplication29
{
class Program
{
static void Main(string[] args)
{
MyStruct ms = new MyStruct(5);
string s = ms.ToString();
Console.WriteLine(s);
}
}
struct MyStruct
{
private int m_SomeInt;
public MyStruct(int someInt)
{
m_SomeInt = someInt;
}
public int SomeInt
{
get
{
return m_SomeInt;
}
}
}
}
和所述MSIL(经由 ILDASM ),用于Main方法是这样的:
IL_0000: ldloca.s ms
IL_0002: ldc.i4.5
IL_0003: call instance void ConsoleApplication29.MyStruct::.ctor(int32)
IL_0008: ldloca.s ms
IL_000a: constrained. ConsoleApplication29.MyStruct
IL_0010: callvirt instance string [mscorlib]System.Object::ToString()
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: ret
现在,尽管没有拳击通话发生,如果你检查的关于约束+呼叫的virt 的文档,你会发现它指出,拳击确实发生。 OOO
引用:
如果thisType是值类型和 thisType没有实现方法 然后PTR解除引用,盒装,和 因为“这个”指针传递 callvirt方法指令。
相信调用toString,的Equals和GetHashCode结果在拳击如果结构不覆盖的方法。