C# 对值类型调用方法

C# 对值类型调用方法,c#,methods,clr,value-type,C#,Methods,Clr,Value Type,如果我在这里出错,请阻止我 如果我理解正确,当我对一个类的实例调用一个方法时,JIT编译器会找到对应于实例类型的type对象,然后在其中找到对实际方法代码的引用 我的问题是,这如何适用于值类型?我的印象是,值类型不像引用类型那样具有类型对象指针。如果是这种情况,当调用某个方法时,CLR如何导航到该方法代码?称为装箱或自动装箱,如果您调用某个方法,CLR将自动从值类型实例化相应的类 关于这方面的更多信息,请考虑一个示例,假设我们有以下结构: public struct Test { pub

如果我在这里出错,请阻止我

如果我理解正确,当我对一个类的实例调用一个方法时,JIT编译器会找到对应于实例类型的type对象,然后在其中找到对实际方法代码的引用


我的问题是,这如何适用于值类型?我的印象是,值类型不像引用类型那样具有类型对象指针。如果是这种情况,当调用某个方法时,CLR如何导航到该方法代码?

称为装箱或自动装箱,如果您调用某个方法,CLR将自动从值类型实例化相应的类


关于这方面的更多信息,请考虑一个示例,假设我们有以下结构:

public struct Test
{
    public void TestMethod()
    {            
    }
}
以下是它的IL代码:

.class public sequential ansi sealed beforefieldinit ConsoleApplication.Test
    extends [mscorlib]System.ValueType
{
    .pack 0
    .size 1

    .method public hidebysig 
        instance void TestMethod () cil managed 
    {
        // Method begins at RVA 0x21dc
        // Code size 1 (0x1)
        .maxstack 8

        IL_0000: ret
    } // end of method Test::TestMethod

}
好的,现在因为C#编译器静态地知道
Test
的类型,所以它可以进行重载解析并找到被调用的确切的
TestMethod
。然后它发出MSIL将参数推送到MSIL虚拟堆栈上,它需要一个指向
Test
的指针类型的参数,编译器在不装箱的情况下处理该参数,并发出包含对该特定方法的元数据引用的调用指令

.locals init (
        [0] valuetype ConsoleApplication.Test test
    )

IL_0000: ldloca.s test
IL_0002: initobj ConsoleApplication.Test
IL_0008: ldloca.s test
IL_000a: call instance void ConsoleApplication.Test::TestMethod()
对于
ToString
GetHashCode
,编译器使用,因为这些方法可能会重载

IL_0002: initobj ConsoleApplication.Test
IL_0008: ldloca.s test
IL_000a: constrained. ConsoleApplication.Test
IL_0010: callvirt instance int32 [mscorlib]System.Object::GetHashCode()
受约束的操作码允许IL编译器调用虚拟机 函数以统一的方式运行,与ptr是否为值类型无关 或引用类型。使用受约束的前缀也可以避免 值类型的潜在版本控制问题。如果约束 未使用前缀,必须根据是否 值类型是否重写System.Object的方法。例如 如果值类型V重写Object.ToString()方法,则调用 V.发出ToString()指令;如果没有,则返回方框说明 并发出callvirt Object.ToString()指令。A. 在前一种情况下,如果覆盖被禁用,可能会出现版本控制问题 之后删除,在后一种情况下,如果以后添加了覆盖,则删除

对于
GetType
方法,需要装箱,因为它是非虚拟的,并且是在
对象中定义的

IL_0002: initobj ConsoleApplication.Test
IL_0008: ldloc.0
IL_0009: box ConsoleApplication.Test
IL_000e: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()

问题是,如果我对一个整数调用CompareTo,那么在生成的IL中就不会调用“box”操作。例如,当我调用GetType时,会出现这种情况,但那是因为GetType是在Object上定义的,而不是在Int32上定义的。哇,我想这是一个简单的问题,我在大学时代的理论知识和谷歌搜索的收益率上挖掘了一些,而且,c#中的值类型不是原始的,它们仍然是有自己方法的对象,但是,它们的实例化和处理方式与引用不同,在调用需要引用的方法时需要装箱。在该上下文中,CompareTo不需要装箱,因为您将int与int进行比较,将值类型与值类型进行比较也是如此,因为该方法是在Int32中实现的,当您创建int时,它已经在内存中了,不需要设置新的引用