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