3

==オペレーターは実際にC#でどのように機能しますか?クラスAのオブジェクトを比較するために使用された場合、 Aのすべてのプロパティを一致させようとしますか、それとも同じメモリ位置(または他の何か)へのポインタを探しますか?

架空の例を作成しましょう。Twitter APIを利用するアプリケーションを作成しています。このアプリケーションには、Tweetクラスがあり、テキスト、送信者、日付と時刻、ソースなど、単一のツイートのすべてのプロパティがあります。クラスTweetのオブジェクトを比較して同等性を確認する場合、私はただ使うことができます:

Tweet a, b;
if (a == b)
{
//do something...
}

それは、 abの間のTweetクラスのすべてのプロパティの同等性をチェックしますか?

そうでない場合、正しいアプローチは==、すべてのフィールドの同等性を明示的にチェックするために演算子をオーバーロードすることですか?

更新:最初の2つの答えから、私は次のように仮定するのが正しいですか?

  • ==演算子またはEqualsメソッドがクラスに対してオーバーロードされていない場合、オブジェクト==クラスの演算子が使用されます。
  • オブジェクトクラスの==演算子は、メモリ位置が等しいかどうかをチェックします。
  • このタスクを実行するには、==演算子またはEqualsメソッドをオーバーロードする必要があります。
  • オーバーロードでは、プロパティの等価性を手動でチェックする必要があるため、半自動で、たとえばループでそれを行う方法はありません

更新#2: Yuriyは、リフレクション==を使用して演算子のプロパティの等価性をチェックできるとコメントしました。これはどのように行うことができますか?サンプルコードを教えてください。ありがとう!

4

5 に答える 5

4

==参照型の場合、演算子とメソッドの両方のデフォルトの実装は、Equals()両方のオブジェクトが同じ参照を持ち、したがって同じインスタンスであることを確認するだけです。

2つの異なるオブジェクトの内容が等しいことを確認したい場合は、何らかの方法で自分でそれを行うためのコードを作成する必要があります。リフレクションを使用することは可能ですが(MbUnitテストフレームワークはこれらの線に沿って何かを実行します)、パフォーマンスが大幅に低下し、とにかく期待どおりに機能しない可能性が高いため、==または手動Equalsで実装する必要がありますGetHashCode

于 2009-10-29T00:52:53.993 に答える
3

MSDNには、その方法の良いがあります。

   public override bool Equals(object o) 
   {
      try 
      {
         return (bool) (this == (DBBool) o);
      }
      catch 
      {
         return false;
      }
   }

次に、==と!=をオーバーロードします。

// Equality operator. Returns dbNull if either operand is dbNull, 
   // otherwise returns dbTrue or dbFalse:
   public static DBBool operator ==(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value == y.value? dbTrue: dbFalse;
   }

   // Inequality operator. Returns dbNull if either operand is
   // dbNull, otherwise returns dbTrue or dbFalse:
   public static DBBool operator !=(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value != y.value? dbTrue: dbFalse;
   }

また、GetHashメソッドをオーバーロードすることを忘れないでください。

編集:

比較でリフレクションを使用するための次の簡単なサンプルを作成しました。これはもっと包括的でなければならないでしょう、人々が私に望んでいるなら、私はそれについてブログをやってみるかもしれません:

public class TestEquals
{
    private int _x;
    public TestEquals(int x)
    {
        this._x = x;
    }

    public override bool Equals(object obj)
    {
        TestEquals te = (TestEquals)obj;
        if (te == null) return false;

        foreach (var field in typeof(TestEquals)
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (!field.GetValue(this).Equals(field.GetValue(te)))
                return false;
        }
        return true;
    }
}
于 2009-10-29T00:40:10.500 に答える
2

適切なアプローチは、ここで説明するように、==演算子に加えてTweetクラスのequalsメソッドをオーバーロードすることです。

于 2009-10-29T00:33:24.023 に答える
1

それは、aとbの間のTweetクラスのすべてのプロパティの同等性をチェックしますか?

いいえ

そうでない場合、正しいアプローチは、==演算子をオーバーロードして、すべてのフィールドの等価性を明示的にチェックすることですか?

==演算子をオーバーロードするか、Equals関数をオーバーロードすることができます。

編集

@Yuriyは、すべての非公開変数を比較するための良い例を示しました。私も例を書いたので、ここにあります(私はプロパティを比較します)

class TwitterItem
{
    private string myValue = "default value";
    public string Value1
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value2
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value3
    {
        get { return myValue; }
        set { myValue = value; }
    }

    public override bool Equals(object obj)
    {
        if (base.Equals(obj)) return true;

        Type type = typeof(TwitterItem);
        PropertyInfo[] properties = type.GetProperties();

        foreach (PropertyInfo property in properties)
        {
            if (false == property.GetValue(this, null).Equals(property.GetValue(obj, null)))
                return false;
        }

        return true;
    }
}
于 2009-10-29T00:34:11.533 に答える
1

リフレクションを使用してプロパティを比較できます。

var a = new Entity() { Name = "test", ID = "1" };
var b = new Entity() { Name = "test", ID = "1" };
var c = new Entity() { Name = "test", ID = "2" };
System.Diagnostics.Debug.WriteLine(a.Equals(b));//Returns true
System.Diagnostics.Debug.WriteLine(a.Equals(c));//Returns false


public class Entity
{
    public string Name { get; set; }
    public string ID { get; set; }
    public override bool Equals(object obj)
    {
        var t = obj.GetType();
        foreach (var p in t.GetProperties())
        {
            if (t.GetProperty(p.Name).GetValue(obj, null) != t.GetProperty(p.Name).GetValue(this, null))
                return false;
        }
        return true;
    }
}
于 2009-10-29T01:00:50.030 に答える