1

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

    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 返回 true,但它们并不相等是有道理的。但是,== 和 .Equals 之间的确切区别究竟是什么?

在情况 3 中,使用带有字符串的 '==' 运算符比较它们的值而不是内存地址。

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

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

4

4 回答 4

3

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

但是,当编译器看到a.Equals(b)时,它会生成对a'Equals方法的调用,这是在运行时确定的,因为它是一个虚拟方法。如果a是一个字符串,那么它将调用进行字符串比较的重载(如您所料)。如果a是其他对象,那么Equals如果它有一个对象,它将调用该对象的重载方法,或者object.Equals(它进行ReferenceEquals比较)如果它没有。

于 2010-12-07T21:45:49.503 回答
0

a.Equals(b)只会做你写过代码的事情。这只是一个虚拟方法调用。

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

于 2010-12-07T21:42:51.250 回答
0

你是如何在 Class1 中实现 Equals() 的?如果您不提供覆盖 Equals 的方法,它将使用默认的 Equals 方法,该方法仅比较参考值。

于 2010-12-07T21:44:35.793 回答
0

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

== 是再次检查引用的运算符。

湾。因为 equals 是 Object 类中的方法,所以它可以被覆盖并且可以用来做任何事情,或者比较对象内部的值,比较引用或计算哈希码并比较它们。因此,在 String 类的情况下,equals 方法已被覆盖以比较传递给它的对象的值。

于 2016-01-29T10:43:48.480 回答