ホームページ > バックエンド開発 > C#.Net チュートリアル > C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

高洛峰
リリース: 2016-12-16 09:45:15
オリジナル
1773 人が閲覧しました

まず CLR の基本的な値の型間の比較を見て、最初にコードを見てみましょう:

            int age1 = 30;            int age2 = 30;

            Console.WriteLine("int == int: {0}", age1 == age2);
            Console.WriteLine("int == int: {0}", age2 == age1);
            Console.WriteLine("int Equals int: {0}", age1.Equals(age2));
            Console.WriteLine("int Equals int: {0}", age2.Equals(age1));
            Console.WriteLine("int ReferenceEquals int: {0}", object.ReferenceEquals(age1, age2));
            Console.WriteLine("int ReferenceEquals int: {0}", object.ReferenceEquals(age2, age1));

            Console.ReadLine();
ログイン後にコピー

実行結果:

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

同じ基本的な値の型 (上記のコード例ではすべて int) の場合、== とEquals() 値型の場合、ReferenceEquals() は 2 つのオブジェクトの参照が等しいかどうかを判断するため、比較結果は同じです。これは、各判断の前にボックス化操作を実行する必要があるためです。つまり、毎回一時オブジェクトが生成されます。したがって、 false を返すことはありません。次に、コード内の age2 の型をバイト型に変更すると、比較結果はどうなるでしょうか。実行結果を見てください:

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

age1.Equals(age2) と age2.Equals(age1) の結果が異なることがわかります。基本的な値の型の比較では、== は「値」の内容を比較します。2 つのオブジェクトの「値」が同じである場合、2 つのオブジェクトは「==」になりますが、Equals() はそれ以上のことを行います。実はEqual()には「暗黙的な変換」の処理があり、上のコードのage1.Equals(age2)はint.Equals(int)と等価であり、バイトデータを暗黙的にInt型データに変換できるということです。したがって、age1.Equals(age2) の結果は true となり、age2.Equals(age1) は byte.Equals(byte) と等価になりますが、int 型データは暗黙的に byte 型に変換できません。データの精度。実際、age2.Equals(age1) の Equals() は次のコードのようになります:

        public override bool Equals(object obj)
        {            if (!(obj is Byte))
            {                return false;
            }            return m_value == ((Byte)obj).m_value;
        }
ログイン後にコピー

明示的な変換の場合、この時点では age2.Equals((byte)age1) の結果は true になります。 。

文字列型間の比較について話しましょう。文字列は「不変」であるため、特別な参照型です。まずコードを見てみましょう:

            string name1 = "Jack";            string name2 = "Jack";            object o1 = name1;            object o2 = name2;

            Console.WriteLine("name1 == name2: {0}", name1 == name2);
            Console.WriteLine("name1 Equals name2: {0}", name1.Equals(name2));

            Console.WriteLine("o1 == o2: {0}", o1 == o2);
            Console.WriteLine("o1 Equals o2: {0}", o1.Equals(o2));

            Console.WriteLine("o1 == name2: {0}", o1 == name2);
            Console.WriteLine("o1 Equals name2: {0}", o1.Equals(name2));

            Console.WriteLine("name1 ReferenceEquals name2: {0}", object.ReferenceEquals(name1, name2));
            Console.WriteLine("o1 ReferenceEquals o2: {0}", object.ReferenceEquals(o1, o2));

            Console.ReadLine();
ログイン後にコピー

上記のコードの実行結果:

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

比較結果はすべて真です。これから 1 つずつ説明します。 name1 と name2 は両方とも "Jack" を格納しているため、name1 と name2 は実際には同じオブジェクトであるため、name1==name2 と name1.Equals(name2) の比較結果は同じであると言う人もいます。おそらく、その考えは正しいでしょう。 .NET Reflector ツールで文字列のソース コードを表示すると、次のコード部分が表示されます:

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

演算子 == は実際には Equals() を返します。したがって、name1==name2 と name1.Equals(name2) の比較結果が同じになる理由の説明は、「name1 と name2 は実際には同じオブジェクトである」よりも、この説明の方が直感的だと思います。

文字列型の特殊性により、CLR は文字列オブジェクトを通じて複数の同一の文字列コンテンツを共有できることがわかっています。そのため、上記の name1 と name2 は同じ場所を指し、次の o1 == o2、o1 == name2 と object.ReferenceEquals(name1, name2) の比較結果はどちらも true であり、このステートメントも検証されます (実際、object.ReferenceEquals(name1, o2) も true です)。しかし、name1 と name2 の割り当てが次のようになったらどうなるでしょうか?

            string name1 = new string(new char[] { 'J', 'a', 'c', 'k' });
            string name2 = new string(new char[] { 'J', 'a', 'c', 'k' });
ログイン後にコピー

実行結果を見てください:

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

name1==name2 と name1.Equals(name2) の比較結果は、理解しやすいものです。 上で述べたように、operator== は実際には Equals() (For の場合) を返します。参照型の場合、Equals() はマネージド ヒープに格納されている内容を比較するため、結果は同じになります。ただし、オブジェクト o1 と o2 を比較すると、o1 == o2 と o1.Equals(o2) の結果は異なります。 == of object オブジェクトは型オブジェクト ポインターを比較します。o1 と o2 は 2 つのオブジェクトであり、それらの型オブジェクト ポインターは異なる必要があります。Equals() はマネージド ヒープに格納されている o1 と o2 の内容を比較するため、o1.Equals (o2) は次のようになります。真実。これは、次の o1 == name2 が false であり、o1.Equals(name2) が true であることも示しています。

まず object.ReferenceEquals の内部コードを見てみましょう:

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

これで、object.ReferenceEquals(name1, name2) と object.ReferenceEquals(o1, o2) の結果が次のようになることを簡単に理解できるはずです。どちらも false です。実際には、これらはオブジェクトの 2 つの == 問題です。

最後に、カスタム参照型の比較について話しましょう。

    class MyName
    {
        private string _id;
        public string Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public MyName(string id)
        {
            this.Id = id;
        }
    }
ログイン後にコピー

上記の name1 と name2 の宣言を次のように変更します。

            MyName name1 = new MyName("12");
            MyName name2 = new MyName("12");
ログイン後にコピー

その他は変更されず、実行結果は次のようになります。

C# の ==、Equals()、ReferenceEquals() の違いを一度に理解する

name1 と name2 は 2 つの完全に異なるオブジェクトです。比較結果がすべて false であることは簡単に理解できるはずです。




C# の ==、Equals()、ReferenceEquals() の違いを一度に理解するための関連記事については、PHP 中国語 Web サイトに注目してください。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート