关于 .Equals() 与 == 运算符以及基元与对象比较的混淆

2024-03-27

考虑这段代码:

int a = 0;
short b = 0;
int c = 0;
object a1 = a;
object b1 = b;
object c1 = c;

Console.WriteLine(1);
//comparing primitives - int vs. short
Console.WriteLine(a == b);
Console.WriteLine(b == a);
Console.WriteLine(a.Equals(b));
Console.WriteLine(b.Equals(a));

Console.WriteLine(2);
//comparing objects - int vs. int
Console.WriteLine(c1 == a1);
Console.WriteLine(a1 == c1);
Console.WriteLine(c1.Equals(a1));
Console.WriteLine(a1.Equals(c1));

Console.WriteLine(3);
//comparing objects - int vs. short
Console.WriteLine(a1 == b1);
Console.WriteLine(b1 == a1);
Console.WriteLine(a1.Equals(b1)); //???
Console.WriteLine(b1.Equals(a1));

它打印这个输出:

1
True
True
True
False
2
False
False
True
True
3
False
False
False
False

我知道的;什么是清楚的

第2节: ==仅当与对象一起使用时,运算符比较内存中由两个不同名称引用的一个对象(不是很常见,但可能会发生),才会返回 true。Equals()方法比较对象的内容(值)。该网站的许多答案中都提到了这一点。

第1节: Using ==运算符,编译器将“较小”类型转换为“较大”(short to int)并比较原始值。操作数(变量)的顺序并不重要。的结果Equals()最后一行可能会令人困惑,因为它返回 false(不比较值),但它是可以理解的。这里的顺序很重要。正如本文中所了解到的answer https://stackoverflow.com/a/21273904/1474519,必须选择最佳的过载。它由第一个变量的类型选择:short.Equals(short)。但是之后int无法转换为“较小”类型(short),因此没有进行比较并且方法返回 false。

问题:

  1. 我上面的理解正确吗?
  2. 为什么第 3 节的最后两行(使用Equals()) 都返回 false?为什么与第 1 部分第 3 行有差异?为什么不进行重载和值比较?它变得非常抽象,我找不到原因。

在第 1 节第 3 行

int a = 0;
short b = 0;
Console.WriteLine(a.Equals(b));

你称这种超载为int: bool Equals(int other), 因为b(短)可以隐式转换为int所以选择这个重载。它返回 true。在第 3 节第 3 行

int a = 0;
short b = 0;
object a1 = a;
object b1 = b;
Console.WriteLine(a1.Equals(b1)); //???

另一个超载int (not object, 因为Equals是虚拟方法)被调用:bool Equals(object other)。让它返回 trueother应该具有完全相同的类型(int),但这确实是short所以它返回 false。拳击与此处无关,您可以通过以下方式验证:

int a = 0;            
int c = 0;
object a1 = a;
object c1 = c;
// yes, different objects
Console.WriteLine(a1 == c1); // false
// still equal, because both are boxed ints
Console.WriteLine(a1.Equals(c1)); // true

至于理解,我认为文档 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-comparison-operator包含所有相关信息。只要记住:

  1. Both ==运算符和Equals方法可以在类中手动定义,因此理论上可以做任何事情。您的理解仅与“默认”行为有关。

  2. ==不是常识意义上的虚拟,不像Equals方法。所以当你这样做时a1 == b1 - ==在编译时定义中调用(基于类型a1 and b1),但是当你打电话时a1.Equals(b1)- 它是虚拟调度的,因此调用的方法是在运行时定义的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于 .Equals() 与 == 运算符以及基元与对象比较的混淆 的相关文章

随机推荐