使用 [==] 运算符和 .Equals() 的 Int、Char、Object 数据类型

Int, Char, Object Datatypes using [==] operator & .Equals()

我对这段代码感到困惑,这两种情况有什么区别?为什么结果不一样?

Example Number 1 - 没有相同的 datatype 和相同的值,但它 returns true

的相同结果
 int value1 = 'a';
 char value2 ='a'; 
 Console.WriteLine(value1 == value2);
 Console.WriteLine(value1.Equals(value2));



Example Number 2 - 它们具有相同的 datatype 和相同的值,但是 returns false & true

object obj1 = "Object One";
object obj2 = new string("Object One".ToCharArray());
Console.WriteLine(obj1 == obj2);
Console.WriteLine(obj1.Equals(obj2));

Example1

int 的值为 97char 的值为 97。 (参见 ASCII
两者都是值类型,所以每次都会比较值。

Example2

字符串是引用类型。
所以使用 .Equals 比较值(相同)和 == 比较参考,这是不同的。

您问题中看似简单的代码实际上包含很多内容,所以让我们一步一步来处理它。请注意,发生了太多事情,我可能会错过一些东西,请使用评论字段。

第一段代码优先:

int value1 = 'a';
char value2 ='a'; 
Console.WriteLine(value1 == value2);
Console.WriteLine(value1.Equals(value2));

这一行:

int value1 = 'a';

应该会提示您此代码行为的原因是什么。有一个从 charint 的静默转换。事实上,编译的内容根本没有提到这个变量的 char ,它是一个数字。分配给 int 变量的数字是 a 的代码点值,即 97。

第一次比较:

value1 == value2

是在 int 上使用 == 运算符完成的,因此实际上,完成了纯数字比较,就好像该字符是一个数字一样。同样的静默转换在这里发生,字符被转换为数字。由于是相同的字符和相同的转换,按理说,您从这个比较中最终得到的也是 97。

This is mentioned in the spec under section 6.1.2, Implicit numeric conversions:

The implicit numeric conversions are:
...
From char to ushort, int, uint, long, ulong, float, double, or decimal

也就是说写出来的实际上相当于:

97 == 97

第二次比较:

value1.Equals(value2)

使用完全相同的转换完成,因此您有:

97.Equals(97)

因此,让我们通过添加显式强制转换并将代码更改为编译器所见的内容来使第一段代码超级清晰:

// int value1 = (int)'a';                        // 97
int value1 = 97;
char value2 = 'a';
Console.WriteLine(value1 == (int)value);         // 97 == 97
Console.WriteLine(value1.Equals((int)value2));   // 97.Equals(97);

我还请LINQPad给我看看这两条语句的反编译:

int a = 97;
int a = 'a';

它们都编译为:

ldc.i4.s 61             // 0x61 = 97

所以要清楚一点,这个静默转换是由编译器完成的,没有运行时代码将字符转换为 声明的 int ,代码执行和编译就像你实际编写的一样

int value1 = 97;

这就是这部分的原因。

现在进入下一部分:

object obj1 = "Object One";
object obj2 = new string("Object One".ToCharArray());
Console.WriteLine(obj1 == obj2);
Console.WriteLine(obj1.Equals(obj2));

这里先声明了两个object变量,这个很重要,然后给它们相同的stringvalue,虽然它们是两个不同的实例.

那么让我们来处理第一个比较:

obj1 == obj2

这是使用为 object 定义的 == 运算符完成的,它比较 references。由于我们已经确定您对第二个变量的时髦字符串构造构造了一个新实例,因此参考比较表明它们是不同的。

它使用 object 上定义的 == 运算符而不是 string 上定义的 on 的原因是因为运算符 已解决在编译期编译时编译器只知道变量是object类型。它们包含字符串的事实,甚至编译器可以 "see" 您刚刚为它们分配字符串的事实,因此它应该使用 string == 运算符,都被忽略了.

但是,当您这样做时:

obj1.Equals(obj2)

那么你正在调用 virtual .Equal(object other) declared in object, which is overriddenstring 中,因此你得到字符串 content 比较,这表明它们是相同的。

所以让我们把第二段代码也变得超级清晰:

object obj1 = "Object One";
object obj2 = new string("Object One".ToCharArray());
Console.WriteLine(obj1.ReferenceEquals(obj2));          // <-- changed
Console.WriteLine(obj1.Equals(obj2));

在示例 1 中,int 和 char 是值类型,因此相等比较(通过 == 或 Equals)默认为逐位比较(如记录 here),因为它们的 none 覆盖== 和他们的 Equals 实现将工作委托给 ==。

true 在这两种情况下都是 return 因为 value1 和 value2 具有相同的二进制表示。

在示例2中,string是一个引用类型,obj1和obj2是对2个string实例的引用,这两个实例恰好具有相同的内容。

但由于它们被声明为对象,并且 == 在编译时解析,编译器的唯一选择是发出引用比较 (=false)

相比之下,obj1.Equals 实际上是对 string.Equals(object) 的调用,它将 return 比较字符串值

示例编号 1

这里发生了 Implicit Conversion,因为两者都是值类型,所以不会比较引用,结果为真。进一步分解,事情是这样的:

int value1 = 'a';           //First converts to ASCII value 97 and then stored in value1
char value2 ='a';           //Stored as a
Console.WriteLine(value1);  //output is 97
Console.WriteLine(value2);  //output is a
Console.WriteLine(value1 == value2);   //compares using implicit conversion. Since value type, so only value comparison and hence true 
Console.WriteLine('a' == 97);          //compares using implicit conversion.  Since value type, so only value comparison and hence true  
Console.WriteLine(value1.Equals(value2)); //compares using implicit conversion.  Since value type, so only value comparison and hence true 

示例编号 2 -

此处,您手动使用了从 Char 到 String 的转换,因此发生了 Explicit Conversion。为了进一步打破它,这是发生了什么:

object obj1 = "Object One";     //string value is stored in Object type variable
object obj2 = new string("Object One".ToCharArray());  //Explicit conversion
Console.WriteLine(obj1);        //Output is Object One
Console.WriteLine(obj2);        //Output is Object One
Console.WriteLine(obj1 == obj2);  //Since == compares both reference and value, hence the false output
Console.WriteLine(obj1.Equals(obj2));  //Equals() compares just the value, hence the true result