关于 .Equals() 与 == 运算符以及基元与对象的比较的混淆
Confusion about comparison by .Equals() vs. == operator and primitives vs. objects
考虑这段代码:
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 节:==
运算符 return仅当与对象一起使用时比较内存中由两个不同名称引用的一个对象(不是非常频繁,但可能会发生)。 Equals()
方法比较对象的内容(值)。 本站很多答案中都提到了。
第 1 部分:使用 ==
运算符,编译器将 'smaller' 类型转换为 'bigger'(short
到 int
)和比较原始值。操作数(变量)的顺序无关紧要。最后一行 Equals()
的结果可能令人困惑,因为它 return 是假的(不比较值),但它是可以理解的。这里的顺序很重要。正如在此 answer 中了解到的,必须选择最佳重载。它由第一个变量的类型选择:short.Equals(short)
。但是 int
无法转换为“更小”类型 (short
),因此没有进行比较,方法 returns false.
问题:
- 我上面的理解正确吗?
- 为什么第 3 节的最后两行(使用
Equals()
)都是 return 错误?为什么第 1 节第 3 行有差异?为什么不进行重载和值比较?越来越抽象了,找不到原因。
除了装箱,这意味着值类型将导致内存中的不同引用,您还必须考虑 Implicit Numeric Conversions
事实上,由于这个原因,你
Console.WriteLine(a.Equals(b));
这给了你一个真实的
但不是这个
Console.WriteLine(b.Equals(a));
这里是另一个例子
static void Main(string[] args)
{
int i = 0;
long L = 0;
Console.WriteLine(1);
//comparing primitives - int vs. short
Console.WriteLine(L.Equals(i)); //true
Console.WriteLine(i.Equals(L));//false
}
第 1 节第 3 行
int a = 0;
short b = 0;
Console.WriteLine(a.Equals(b));
您将 int
的重载称为 bool Equals(int other)
,因为 b
(短)可以隐式转换为 int
,因此选择此重载。 return 是真的。在第 3 节第 3 行
int a = 0;
short b = 0;
object a1 = a;
object b1 = b;
Console.WriteLine(a1.Equals(b1)); //???
int
的另一个重载(不是 object
,因为 Equals
是虚方法)被调用:bool Equals(object other)
。对于 return true other
应该具有完全相同的类型 (int
),但它确实是 short
所以它 returns 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
至于理解,我认为documentation包含了所有相关信息。请记住:
==
运算符和Equals
方法都可以在class中手动定义,理论上可以做任何事情。您的理解仅与 "default" 行为有关。
==
不是常识上的虚拟,不像 Equals
方法。所以当你做 a1 == b1
- ==
在编译时定义调用(基于 a1
和 b1
的类型),但是当你调用 a1.Equals(b1)
- 它实际上是分派的,因此调用方法是在运行时定义的。
考虑这段代码:
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 节:==
运算符 return仅当与对象一起使用时比较内存中由两个不同名称引用的一个对象(不是非常频繁,但可能会发生)。 Equals()
方法比较对象的内容(值)。 本站很多答案中都提到了。
第 1 部分:使用 ==
运算符,编译器将 'smaller' 类型转换为 'bigger'(short
到 int
)和比较原始值。操作数(变量)的顺序无关紧要。最后一行 Equals()
的结果可能令人困惑,因为它 return 是假的(不比较值),但它是可以理解的。这里的顺序很重要。正如在此 answer 中了解到的,必须选择最佳重载。它由第一个变量的类型选择:short.Equals(short)
。但是 int
无法转换为“更小”类型 (short
),因此没有进行比较,方法 returns false.
问题:
- 我上面的理解正确吗?
- 为什么第 3 节的最后两行(使用
Equals()
)都是 return 错误?为什么第 1 节第 3 行有差异?为什么不进行重载和值比较?越来越抽象了,找不到原因。
除了装箱,这意味着值类型将导致内存中的不同引用,您还必须考虑 Implicit Numeric Conversions
事实上,由于这个原因,你
Console.WriteLine(a.Equals(b));
这给了你一个真实的 但不是这个
Console.WriteLine(b.Equals(a));
这里是另一个例子
static void Main(string[] args)
{
int i = 0;
long L = 0;
Console.WriteLine(1);
//comparing primitives - int vs. short
Console.WriteLine(L.Equals(i)); //true
Console.WriteLine(i.Equals(L));//false
}
第 1 节第 3 行
int a = 0;
short b = 0;
Console.WriteLine(a.Equals(b));
您将 int
的重载称为 bool Equals(int other)
,因为 b
(短)可以隐式转换为 int
,因此选择此重载。 return 是真的。在第 3 节第 3 行
int a = 0;
short b = 0;
object a1 = a;
object b1 = b;
Console.WriteLine(a1.Equals(b1)); //???
int
的另一个重载(不是 object
,因为 Equals
是虚方法)被调用:bool Equals(object other)
。对于 return true other
应该具有完全相同的类型 (int
),但它确实是 short
所以它 returns 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
至于理解,我认为documentation包含了所有相关信息。请记住:
==
运算符和Equals
方法都可以在class中手动定义,理论上可以做任何事情。您的理解仅与 "default" 行为有关。==
不是常识上的虚拟,不像Equals
方法。所以当你做a1 == b1
-==
在编译时定义调用(基于a1
和b1
的类型),但是当你调用a1.Equals(b1)
- 它实际上是分派的,因此调用方法是在运行时定义的。