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の型を見て、コンパイル時に呼び出す関数を決定することです。とが両方とも 型の場合、コンパイラは への呼び出しを生成しますが、どちらも 型の場合、コンパイラは への呼び出しを生成します。ababobjectReferenceEqualsstringstring.Equals

ただし、コンパイラがを検出すると、仮想メソッドであるため実行時に決定されるのメソッドa.Equals(b)への呼び出しを生成します。が文字列の場合、(ご想像のとおり) 文字列比較を行うオーバーロードが呼び出されます。が他のオブジェクトである場合、そのオブジェクトにオーバーロードされたメソッドがある場合はそれを呼び出し、ない場合は (比較を行います) 呼び出します。aEqualsaaEqualsobject.EqualsReferenceEquals

于 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 クラスに存在するメソッドであり、渡されたオブジェクトの参照をそれが呼び出されたオブジェクトと比較します。

== は参照を再チェックする演算子です。

b. equals は Object クラスのメソッドであるため、オブジェクト内の値を比較したり、参照を比較したり、ハッシュコードを計算してそれらを比較したりするために、オーバーライドして何でも使用できます。そのため、String クラスの場合、equals メソッドは渡されたオブジェクトの値を比較するためにオーバーライドされています。

于 2016-01-29T10:43:48.480 に答える