В чем разница между a == b и a.Equals (b) в контексте значений и ссылочных типов? - PullRequest
1 голос
/ 08 декабря 2010

Я сталкивался с этим вопросом довольно много раз, и хотя ответы на него имеют смысл, я хотел сам проверить его с помощью простого консольного приложения.

    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 ]

3 голосов
/ 08 декабря 2010

Я думаю, что ключевым моментом, который нужно помнить, является то, что с a == b компилятор определяет, какую функцию вызывать во время компиляции, рассматривая типы a и b.Если a и b имеют тип object, компилятор сгенерирует вызов ReferenceEquals, тогда как если они оба имеют тип string, компилятор сгенерирует вызов string.Equals.

Однако, когда компилятор видит a.Equals(b), он генерирует вызов метода a Equals, который определяется во время выполнения, потому что это виртуальный метод.Если a является строкой, то она вызовет перегрузку, которая выполняет сравнение строк (как вы ожидаете).Если a - это какой-то другой объект, то он вызовет перегруженный метод Equals для этого объекта, если он у него есть, или object.Equals (который выполняет сравнение ReferenceEquals), если этого не происходит.

0 голосов
/ 29 января 2016

a.equals - это метод, присутствующий в классе java.lang.Object, который сравнивает ссылки переданного ему объекта с объектом, для которого он был вызван.

== является оператором для повторной проверки ссылок.

б. Поскольку метод equals является методом в классе Object, он может быть переопределен и может использоваться для любых действий: для сравнения значений внутри объектов, сравнения ссылок или вычисления хеш-кодов и их сравнения. Таким образом, в случае использования класса String метод equals был переопределен для сравнения значений переданных ему объектов.

0 голосов
/ 08 декабря 2010

Как вы реализуете Equals () в Class1? Если вы не предоставите метод для переопределения Equals, он будет использовать метод Equals по умолчанию, который будет просто сравнивать контрольные значения.

0 голосов
/ 08 декабря 2010

a.Equals(b) будет делать только то, для чего вы написали код.Это просто вызов виртуального метода.

Поведение по умолчанию (для ссылочных типов) - просто сравнивать ссылки.

...