“ceq”MSIL命令和object.InternalEquals之间的区别

时间:2011-03-07 21:08:43

标签: c# equals cil

我在ILDASM和Reflector中挖掘,发现:

  1. ==被编译为“ceq”MSIL命令
  2. object.Equals保持原样
  3. object.Equals调用 object.InternalEquals
  4. This问题告诉我如何找出InternalEquals是如何实现的,即在.cpp类中(或者在CLR中的某个地方)。

    我的问题是:

    ceq成为什么?另一个.cpp类中的另一种方法?即它们是完全不同的代码?因此,虽然==和Equals的默认行为看起来是相同的,但它是不同的代码?

3 个答案:

答案 0 :(得分:18)

==运算符并不总是被转换为ceq。类型可以使用operator ==()重载它。例如,System.Decimal执行此操作,它会重载所有运算符,因为它们的实现非常重要,并且抖动没有类型的特殊知识(编译器会这样做)。

你会发现它与Reflector一起作为Decimal.op_Equality()方法。这将引导您进入FCallCompare,这是一种归因于MethodImplOptions.InternalCall的方法。这些方法很特殊,抖动对它们有秘密的了解。您可以通过Rotor中的clr / src / vm / ecall.cpp源代码文件找到它们的实现。它包含所有内部调用函数的表,抖动通过方法名称查找表条目。然后将表中提供的相应C ++函数的地址编译到调用指令中。请注意,自Rotor发布以来,函数名称已更改,搜索FCallAdd,它是表中的下一个条目。这将带您到COMDecimal :: Compare。这会将您带到comdecimal.cpp源代码文件。

x86和x64抖动知道如何直接将ceq操作码转换为机器码而无需辅助函数,它会内联生成本机机器指令。实际生成的代码取决于要比较的值的类型。目标,x64抖动使用SSE指令,x86使用FPU指令来比较浮点值。当然,其他的紧张情绪会以不同的方式实现它们。

像Object.InternalEquals()这样的辅助函数也是一个内部方法,就像FCallCompare一样。您将使用相同的策略来查找实现。

答案 1 :(得分:4)

您看到ceq因为没有超载== - 它正在进行直接引用比较。要做到这一点,它所要做的只是直接比较堆栈上的两个数字;这是它能做的最快的事情。

object.Equals含糊不清;有两个;

x.Equals(y)是一个虚方法,因此可能会被覆盖。根据类型,将发出虚拟呼叫,静态呼叫或受限呼叫,可能具有自定义实施。

object.Equals(x,y)是一个静态方法,它首先检查空值; 2 nulls = true,1 null = false,0 nulls - 调用x.Equals(y)。

但是要专注于这个问题,那就是逻辑 a == on native int;在大多数JIT中,我希望这仍然是一个==对两个整数类型(可能是指针),但JIT变化(或者实际上甚至不存在--MF是一个解释器)。

答案 2 :(得分:2)

是的,他们运行不同的代码。

  • Equals是一种实例方法。
  • ==是一个静态运算符。

可以为自定义类型重新定义两者。

相关问题