我搜索了FCL的源代码,我感到困惑的是string.Equals()
使用Object.ReferenceEquals()
,Object.ReferenceEquals()
使用==
运算符来jugde。然后我无法找到如何定义==
运算符。
原定的运营商定义在哪里?
答案 0 :(得分:27)
这是一种语言用来验证两个值是否相同的运算符。当你的代码被编译时,这个运算符将在CIL中被适当地编译,然后当我们将由CLR执行时,将比较两个值以检查它们是否相同。
例如,这是Main
方法的CIL代码:
编译器为以下程序生成(它是一个控制台应用程序):
class Program
{
static void Main(string[] args)
{
int a = 3;
int b = 4;
bool areEqual = a == b;
Console.WriteLine(areEqual);
}
}
注意IL_0007行。已发出ceq
条指令。这是您正在寻找的==
运营商。
重要提示
当==
没有超载时会发生这种情况。
答案 1 :(得分:17)
当没有重载的==
运算符(如此处)时,编译器会发出ceq
指令。此时不再需要查看C#代码。
比较两个值。如果它们相等,则将整数值1(int32)推送到评估堆栈;否则0(int32)被推到评估堆栈上。
答案 2 :(得分:4)
ceq
从堆栈中获取两个值并给出结果。如果结果值为1则认为它们相等,如果它们不相等则为0。
但是,==
运算符并不总是转换为ceq
。
C#中的==
是ceq
会导致are data types primitives
或do they have custom == operators
或are they references
等。{/ p>
答案 3 :(得分:3)
在C#中重载operator==
是用于调用静态函数的语法糖。与所有重载分辨率一样,重载决策基于对象的静态类型而不是动态类型。让我们再看一下Object.ReferenceEquals
:
public static bool ReferenceEquals (Object objA, Object objB) {
return objA == objB;
}
此处,objA
和objB
的静态类型为Object
。动态类型可以是任何东西;一个字符串,一些其他用户定义的类型,等等;那不重要。编译此函数时,确定调用哪个operator==
是静态确定的,因此您始终可以获得默认的,非重载的,内置语言提供的函数。 .NET可能没有ReferenceEquals
并且让用户执行((object)a) == ((object)b)
,但是具有特定的命名功能来说明正在进行的操作可以提高清晰度。
Object.Equals
只是一个虚函数。因此,选择Equals
基于.Equals(
左侧对象的动态类型,就像任何其他虚函数调用一样。