如何在堆中使用其类型对象找到结构实例的虚拟方法

如何在堆中使用其类型对象找到结构实例的虚拟方法

本文介绍了如何在堆中使用其类型对象找到结构实例的虚拟方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一本书中的代码示例,用于显示何时将值类型装箱:

below is a code example from a book to show when a value type will be boxed:

internal struct Point
{
   private readonly Int32 m_x, m_y;
   public Point(Int32 x, Int32 y) {
      m_x = x;
      m_y = y;
   }

   //Override ToString method inherited from System.ValueType
   public override string ToString() {
      return String.Format("({0}, {1})", m_x.ToString(), m_y.ToString());
   }
}

class Program
{
    static void Main(string[] args) {
       Point p1 = new Point(10, 10);
       p1.ToString();
    }
}

作者说:

我有点明白了,因为 Point 覆盖了 System.ValueType 中的 ToString ,CLR不需要检查类型对象以找到类型的方法表,编译器可以发出直接调用ToString的IL代码.足够公平.

I kind of get what it means, because Point overrides ToString from System.ValueType, CLR doesn't need to check the type object to locate the type’s method table, the compiler can emits IL code that calls ToString directly. Fair enough.

但是,假设 p1 也从 System.ValueType 调用 GetHashCode :

class Program
{
    static void Main(string[] args) {
       Point p1 = new Point(10, 10);
       p1.ToString();
       p1.GetHashCode();
    }
}

因为 Point 结构没有覆盖 System.ValueType 中的 GetHashCode(),所以编译器这次无法直接发出IL代码,因此CLR需要定位类型的方法表以查找 GetHashCode 方法,但是正如作者所说,p1是未装箱的值类型,因此没有类型对象指针,因此CLR如何查找 GetHashCode堆中 Point 结构的类型对象中的方法?

since Point struct doesn't override GetHashCode() from System.ValueType, then compiler cannot emit IL codes directly this time and CLR needs to location the type’s method table to look up GetHashCode method, but as the author says p1 is an unboxed value type, there’s no type object pointer, so how can the CLR look up the GetHashCode method in Point struct's type object in heap?

推荐答案

如果我们查看生成的MSIL,则会看到以下内容:

If we look at the generate MSIL, we see the following:

IL_0000:  ldloca.s    00 // p1
IL_0002:  ldc.i4.s    0A
IL_0004:  ldc.i4.s    0A
IL_0006:  call        System.Drawing.Point..ctor
IL_000B:  ldloca.s    00 // p1
IL_000D:  constrained. System.Drawing.Point
IL_0013:  callvirt    System.Object.ToString
IL_0018:  pop
IL_0019:  ldloca.s    00 // p1
IL_001B:  constrained. System.Drawing.Point
IL_0021:  callvirt    System.Object.GetHashCode
IL_0026:  pop

让我们查找 ECMA-335第III.2.1部分受到约束.:

所以,是的,这确实会引起装箱,但仅当没有覆盖时才会出现,因为 System.Object 方法需要一个类,而不是值类型.但是,如果它被重写,则该方法的 this 指针必须是托管指针,与任何其他valuetype方法相同.

So, yes, this does cause boxing, but only when there is no override, because System.Object methods expect a class, not a valuetype. But if it is overridden, then the this pointer of the method must be a managed pointer, the same as any other valuetype method.

这篇关于如何在堆中使用其类型对象找到结构实例的虚拟方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 14:25