我在ILDASM和Reflector中进行了挖掘,发现:
==被编译为“ ceq” MSIL命令
object.Equals保持不变
object.Equals调用
object.InternalEquals
This问题向我展示了如何找出InternalEquals的实现方式,即在.cpp类(或CLR中的任何位置)中。
我的问题是:
ceq变成什么? .cpp类中的另一个方法?即它们是完全不同的代码吗?因此,尽管==和Equals的默认行为看起来是相同的,但这是不同的代码吗?
最佳答案
==运算符并不总是转换为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一样。您将使用相同的策略来找到实现。