5

よくわからない C# の奇妙な「非対称性」に見舞われました。次のコードを参照してください。

using System;
using System.Diagnostics;
namespace EqualsExperiment
{
    class Program
    {
        static void Main(string[] args)
        {
            object apple = "apple";
            object orange = string.Format("{0}{1}", "ap", "ple");
            Console.WriteLine("1");
            Debug.Assert(apple.Equals(orange));
            Console.WriteLine("2");
            Debug.Assert(apple == orange);
            Console.WriteLine("3");
        }
    }
}

.NET の達人には明らかかもしれませんが、2 番目のアサートは失敗します。

Java では、== はここで Object.ReferenceEquals と呼ばれるものの同義語であることを学びました。C# では、Object.operator== は仮想である Object.Equals を使用すると考えていたため、System.String クラスでオーバーライドされています。

誰かが説明できますか? C# で 2 番目のアサートが失敗するのはなぜですか? 私の仮定のどれが悪いですか?

4

2 に答える 2

7

==演算子はシノニムではなく、さまざまな型に対して定義されている演算子です。

演算子は文字列に対して定義され、==実際にEqualsメソッドを使用します。

public static bool operator ==(string a, string b) {
  return Equals(a, b);
}

ただし、コードでは、文字列に対して演算子を使用していません。オブジェクトに対して使用している==ため、オブジェクトに対して定義された演算子が得られReferenceEquals、比較に使用されます。

使用する演算子のオーバーロードはコンパイル時に決定されるため、オーバーロードを決定するのは変数の型であり、変数が指すオブジェクトの実際の型ではありません。

于 2010-09-16T10:30:49.037 に答える
6

演算子は静的メソッドとして定義されているため、ポリモーフィズムに参加することはできません。したがって、2番目のアサーションは==forの定義を使用しobjectます(変数はとして宣言されているためobject)。これは、参照の同等性のみをテストします。変数がとして宣言された場合string、の==オーバーロードstringが使用され、2番目のアサートが成功します。

于 2010-09-16T10:21:56.500 に答える