在值和引用类型的上下文中,a == b和a.Equals(b)之间有什么区别?

时间:2010-12-07 21:39:17

标签: reference types equals referenceequals

我已经多次遇到过这个问题了,虽然答案很有意义,但我想通过一个简单的控制台应用程序来检查它。

    class Program
{
    static void Main(string[] args)
    {
        // Case 1 : FOR REFERENCE TYPES where class b is a copy of class a
        Class1 a = new Class1("Hello");
        Class1 b = a;
        Console.WriteLine("case 1");
        Console.WriteLine(a.GetHashCode());
        Console.WriteLine(b.GetHashCode());
        Console.WriteLine(a==b); //true
        Console.WriteLine(a.Equals(b)); //true

        // Case 2 : FOR REFERENCE TYPES where class b is not a copy of class a, but it assigned the same values
        // Though the referenced memory addresses are different, the fields of the class are assigned the same values, but will have different hashcodes and are therfore not equal.
        Class1 c = new Class1("Hello");
        Console.WriteLine(" ");
        Console.WriteLine("case 2");
        Console.WriteLine(a.GetHashCode());
        Console.WriteLine(c.GetHashCode());
        Console.WriteLine(a==c);//false
        Console.WriteLine(a.Equals(c));//false

        // Case 3 : FOR REFERENCE TYPES where two strings are assigned the same values, an exception to the way value types behave.
        // using the '==' operstor with strings compares their values not memory addresses.
        string s1 = "hi";
        string s2 = "hi";
        Console.WriteLine(" ");
        Console.WriteLine("case 3");
        Console.WriteLine(s1 == s2);//true
        Console.WriteLine(s1.Equals(s2));//true

        //Case 4 : FOR VALUE TYPES - they are the same when comparing the same type.
        int x = 5;
        int y = 5;
        Console.WriteLine(" ");
        Console.WriteLine("case 4");
        Console.WriteLine(x);
        Console.WriteLine(y);
        Console.WriteLine(x == y);//true
        Console.WriteLine(x.Equals(y));//true

        // Case 5 : Another value type scenario for completeness
        x = y;
        Console.WriteLine(" ");
        Console.WriteLine("case 5");
        Console.WriteLine(x);
        Console.WriteLine(y);
        Console.WriteLine(x.GetType());
        Console.WriteLine(y.GetType());
        Console.WriteLine(x == y);//true
        Console.WriteLine(x.Equals(y));//true

        // Case 6 : Yet Another value type scenario for completeness, with different value types.
        float z = 5;
        Console.WriteLine(" ");
        Console.WriteLine("case 6");
        Console.WriteLine(x.GetType());
        Console.WriteLine(z.GetType());
        Console.WriteLine(x);
        Console.WriteLine(z);
        Console.WriteLine(x == z);//true
        Console.WriteLine(x.Equals(z));//false, as the values being compared are of two different types- int and float. The .Equals method expects them to be the same type.

        // Case 7 : For giggles, Yet Another ref type scenario for completeness, with objects.
        string s3 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
        string s4 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
        object obj1 = s3;
        object obj2 = s4;
        Console.WriteLine(" ");
        Console.WriteLine("case 7");
        Console.WriteLine(obj1.ToString());
        Console.WriteLine(obj2.ToString());
        Console.WriteLine(obj1.GetHashCode());
        Console.WriteLine(obj2.GetHashCode());
        Console.WriteLine(obj1 == obj2);//false - as they refer to different addresses.
        Console.WriteLine(obj1.Equals(obj2));//true - in this case both objects have the same hashcode.
        Console.ReadKey();

    }

    public class Class1
    {
            string name;
            public Class1(string strName)
            {
                name = strName;
            }
     }

}

假设1 :我从常见的回复中了解到,对于引用类型,a == b比较引用,而a.Equals(b)比较引用的实际值。这是在查看我的程序结果时让我失望的。

参考我的程序,在案例2中 - 虽然a和c的引用内存地址不同,但它们的字段被赋予相同的值。仍然a.Equals(c)返回false,因为它们仍然不相等,因为它们具有不同的哈希码。我曾假设他们最初会根据假设1返回真实,但是它们是不正确的。但那么==和.Equals之间究竟有什么区别?

在案例3中,对字符串使用'=='运算符会比较它们的值而不是内存地址。

在案例6中,通过.Equals方法比较的值类型是不同的,而该方法期望它们具有相同的类型。因此它返回false。

我仍然不明白的是案例7.为什么对象在这种情况下具有相同的哈希码?对于漫长的代码感到抱歉,并提前致谢!

4 个答案:

答案 0 :(得分:3)

我认为要记住的一件事是,使用a == b,编译器通过查看ab的类型来确定在编译时调用哪个函数。如果ab都是object类型,编译器将生成对ReferenceEquals的调用,而如果它们都是类型string,编译器将生成对string.Equals的调用。

但是,当编译器看到a.Equals(b)时,它会生成对a的{​​{1}}方法的调用,该方法在运行时确定,因为它是一个虚方法。如果Equals是一个字符串,那么它将调用执行字符串比较的重载(如您所期望的那样)。如果a是其他对象,那么它将调用该对象上的重载a方法(如果它有一个)或Equals(进行object.Equals比较)如果它没有“T

答案 1 :(得分:0)

a.Equals(b)只会执行您编写的代码。这只是一个虚拟方法调用。

默认行为(对于引用类型)只是比较引用。

答案 2 :(得分:0)

如何在Class1中实现Equals()?如果你没有提供一个覆盖Equals的方法,它将使用默认的Equals方法,它只是比较参考值。

答案 3 :(得分:0)

a.equals是java.lang.Object类中的方法,它将传递给它的对象的引用与调用它的对象进行比较。

==是再次检查参考文献的操作员。

湾由于equals是Object类中的方法,因此可以覆盖它并可用于执行任何操作,以比较对象内部的值,比较引用或计算哈希代码并进行比较。 因此,对于String类,equals方法已被覆盖,以比较传递给它的对象的值。