为什么在原始类型实例上调用Object类的某些函数需要装箱?

时间:2010-02-01 19:14:13

标签: c# .net .net-internals

我发现如果我运行以下代码行。

int i = 7;
i.GetHashCode(); //where GetHashCode() is the derived
                 //function from System.Object

没有完成拳击,但是如果我调用i.GetType()(来自System.Object的另一个派生函数)代替GetHashCode(),则需要拳击才能调用GetType(),为什么不能在没有装箱的情况下直接调用原始类型实例上的GetType(),而可以在没有装箱的情况下调用GetHashCode()

3 个答案:

答案 0 :(得分:8)

这里的关键是GetType()不是虚拟的,不能被覆盖。由于结构实际上是sealed,因此方法不能覆盖任何 more 而不是结构,因此运行时和编译器可以将已被覆盖的结构方法视为静态调用

如果您编写一个结构(罕见),应该覆盖所有方法,例如ToString()Equals()GetHashCode(),正是出于这个原因。如果你不这样做必须装箱。但是,GetType() 无法覆盖,因此需要装箱。

这实际上会导致一些奇怪的边缘情况Nullable<T>和拳击,因为空Nullable<T>框到null,所以:

int i = obj.GetHashCode(); // fine
Type t = obj.GetType(); // boom

答案 1 :(得分:2)

我认为原因是GetHashCode直接在System.Int32上实现,你调用System.Int32 :: GetHashCode()。如果在值类型上调用已知成员函数,则无需使用框。

答案 2 :(得分:1)