关于通过.Equals()与==运算符和原语与对象进行比较的混淆

时间:2017-10-19 11:57:46

标签: c# comparison equals

考虑以下代码:

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节:使用==运算符,编译器将“较小”类型转换为“更大”(shortint)并比较原始值。操作数(变量)的顺序无关紧要。最后一行中Equals()的结果可能会令人困惑,因为它返回false(不比较值),但可以理解。订单在这里很重要。正如在此answer中所了解的那样,必须选择最佳过载。它由第一个变量的类型选择:short.Equals(short)。但是int无法转换为'较小'类型(short),因此没有进行比较,方法返回false。

问题:

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

2 个答案:

答案 0 :(得分:2)

在第1节第3行

create_model_info(architecture)

你称之为int a = 0; short b = 0; Console.WriteLine(a.Equals(b)); int的重载,因为bool Equals(int other)(短)可以隐式转换为b,因此选择了此重载。它返回true。在第3节第3行

int

int a = 0; short b = 0; object a1 = a; object b1 = b; Console.WriteLine(a1.Equals(b1)); //??? 的另一个重载(不是int,因为object是虚方法)被称为:Equals。要返回true,bool Equals(object other)应该具有完全相同的类型(other),但它确实是int,因此它返回false。拳击与此无关,您可以通过以下方式验证:

short

至于理解,我认为documentation包含所有相关信息。请记住:

  1. 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 运算符和==方法都可以在类中手动定义,因此理论上可以做任何事情。您的理解仅与“默认”行为有关。

  2. Equals方法不同,
  3. ==在常识中不是虚拟的。因此,当您在编译时定义时调用Equals - a1 == b1(基于==a1的类型),但是当您调用b1时 - 它实际上是调度的,因此调用方法是在运行时定义的。

答案 1 :(得分:1)

除了拳击意味着值类型会在内存中产生不同的引用,你必须考虑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
        }