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

dav*_*ode 3 c# conditional

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

Example Number 1- 没有相同的datatypew /相同的值,但它返回相同的结果true

 int value1 = 'a';
 char value2 ='a'; 
 Console.WriteLine(value1 == value2);
 Console.WriteLine(value1.Equals(value2));
Run Code Online (Sandbox Code Playgroud)



Example Number 2- 它们具有相同的datatypew /相同的值,但它返回false & true

object obj1 = "Object One";
object obj2 = new string("Object One".ToCharArray());
Console.WriteLine(obj1 == obj2);
Console.WriteLine(obj1.Equals(obj2));
Run Code Online (Sandbox Code Playgroud)

ang*_*son 10

在您的问题看似简单的代码中实际上有很多事情发生,所以让我们一步一步地处理它.请注意,有很多事情可能会遗漏,请使用评论字段.

第一段代码:

int value1 = 'a';
char value2 ='a'; 
Console.WriteLine(value1 == value2);
Console.WriteLine(value1.Equals(value2));
Run Code Online (Sandbox Code Playgroud)

这一行:

int value1 = 'a';
Run Code Online (Sandbox Code Playgroud)

应该给你一个关于这段代码行为的原因的提示.从a char到a的静默转换int.事实上,编译的内容根本没有提到char这个变量,它是一个数字.分配给int变量的编号是代码点值a,即97.

第一次比较:

value1 == value2
Run Code Online (Sandbox Code Playgroud)

使用==运算符来完成int,因此实际上,完成了纯数字比较,就好像字符是数字一样.这里进行相同的静默转换,将字符转换为数字.由于它是相同的字符和相同的转换,因此你也可以从这个比较中得到97.

这在第6.1.2节隐式数字转换的规范中提到:

隐式数值转换为:
......
charushort,int,uint,long,ulong,float,double,或者decimal

这意味着所写的内容实际上相当于:

97 == 97
Run Code Online (Sandbox Code Playgroud)

第二个比较:

value1.Equals(value2)
Run Code Online (Sandbox Code Playgroud)

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

97.Equals(97)
Run Code Online (Sandbox Code Playgroud)

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

// 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);
Run Code Online (Sandbox Code Playgroud)

我还要求LINQPad向我展示这两个语句的反编译:

int a = 97;
int a = 'a';
Run Code Online (Sandbox Code Playgroud)

他们都编译为:

ldc.i4.s 61             // 0x61 = 97
Run Code Online (Sandbox Code Playgroud)

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

int value1 = 97;
Run Code Online (Sandbox Code Playgroud)

这就是这一部分的原因.

现在进入下一部分:

object obj1 = "Object One";
object obj2 = new string("Object One".ToCharArray());
Console.WriteLine(obj1 == obj2);
Console.WriteLine(obj1.Equals(obj2));
Run Code Online (Sandbox Code Playgroud)

在这里,您首先声明两个object变量,这很重要,然后给它们相同的string ,尽管它们是两个不同的实例.

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

obj1 == obj2
Run Code Online (Sandbox Code Playgroud)

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

它之所以使用==定义的运算符object,而不是on on on string是因为运算符在编译时被解析,并且在编译时编译器只知道变量是类型的object.事实上,它们包含字符串,即使编译器可以"看到"你刚刚为它们分配了字符串,以便它应该使用string ==运算符,这一事实也会被忽略.

但是,当你这样做时:

obj1.Equals(obj2)
Run Code Online (Sandbox Code Playgroud)

然后,您呼叫的虚拟 .Equal(object other)中声明object,这是覆盖string,这样的话你得到的字符串的内容比较,这表明它们是相同的.

所以让我们让第二段代码变得非常清晰:

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