2

私は次のクラスを持っています:

 public class MyDocuments
    {
        public DateTime registeredDate;
        public string version;
        public List<Document> registeredDocuments;
    }

    public class Document
    {
        public string name;
        public List<File> registeredFiles;
    }

    public class File
    {
        public string name;
        public string content;
    }

にいくつかのドキュメントがあるMyDocumentsのインスタンスがありますList<Document> registeredDocument。ユーザーから新しいものを受け取りList<Document>ます。

新しいオブジェクトがリストに存在しないことを確認するにはどうすればよいですか?参照ではなく値で比較したい。

Listの代わりにHashSetを使用することを考えています。これは適切なアプローチですか?

4

5 に答える 5

2

等価比較はどのように実行されますか?

BCL クラスが何らかのタイプのオブジェクト間で等価性チェックを実行する必要がある場合はTIEqualityComparer<T>. このような実装を取得するために、フレームワークはEqualityComparer<T>.Default.

ドキュメントに記載されているように、このプロパティは次のIEqualityComparer<T>ようになります。

は、型 T がインターフェイスを Default property実装しているかどうかをチェック し、そうであれば、その実装を使用する を返します。それ以外の場合は、およびによって提供されるオーバーライドを使用する を 返します。System.IEquatable<T>EqualityComparer<T>EqualityComparer<T>Object.EqualsObject.GetHashCodeT

私のオプションは何ですか?

したがって、一般に、等価比較の実行方法を指定するには、次のことができます。

  1. IEqualityComparer<T>等値チェックを実行するクラスまたはメソッドにの実装を明示的に提供します。このオプションは ではあまり目立ちませんList<T>が、多くの LINQ メソッド ( などContains) でサポートされています。
  2. クラスに を実装させIEquatable<T>ます。これによりEqualityComparer<T>.Default、この実装が使用され、 type のオブジェクトを比較するための明白な「自然な」方法がある場合はいつでも適切な選択になりますT
  3. object.GetHashCodeandobject.Equalsを実装せずにオーバーライドしますIEqualityComparer<T>。ただし、これは単純に #2 の劣ったバージョンであり、AFAIK は常に避ける必要があります。

どのオプションを選択しますか?

経験則としては、 class のオブジェクトを比較する明白で自然な方法がある場合は、Tそれを実装することを検討してくださいIEquatable<T>。これにより、追加の関与なしにフレームワーク全体で比較ロジックが使用されるようになります。明白な候補がない場合、またはデフォルトとは異なる方法で比較したい場合は、独自IEqualityComparer<T>に実装し、その実装を引数として、等価チェックを実行する必要があるクラスまたはメソッドに渡します。

于 2012-11-26T19:38:46.577 に答える
1

メソッドを実装する必要がありEquals()、おそらくそれGetHashCode()も同様です。例については、この回答を参照してください。

于 2012-11-26T19:12:13.807 に答える
1

を実装する必要がありますIEquatable<T>

このインターフェイスをカスタム オブジェクトに実装すると、オブジェクトの実装を使用して等価チェック (Contains、IndexOf など) が自動的に実行されます。

于 2012-11-26T19:12:51.657 に答える
0

object.Equalsメソッドをオーバーライドします。

これはドキュメントから直接の例です

public class Person
{
   private string idNumber;
   private string personName;

   public Person(string name, string id)
   {
      this.personName = name;
      this.idNumber = id;
   }

   public override bool Equals(Object obj)
   {
      Person personObj = obj as Person; 
      if (personObj == null)
         return false;
      else 
         return idNumber.Equals(personObj.idNumber);
   }

   public override int GetHashCode()
   {
      return this.idNumber.GetHashCode(); 
   }
}

このメソッドは、等しいEqualsかどうかに関係なくブール値を返します。objthis

于 2012-11-26T19:11:46.237 に答える
0

最上位レベルでは次のようになり、下位レベルまで続いています。

public class MyDocuments
{
    public DateTime registeredDate;
    public string version;
    public HashSet<Document> registeredDocuments;
    public override bool Equals(Object o)
    {
        if( !(o is MyDocuments) ) return false;
        MyDocuments that = (MyDocuments)o;
        if( !String.Equals(this.version, that.version) ) return false;
        if( this.registeredDocuments.Count != that.registeredDocuments.Count ) return false;
        // assuming registeredDate doesn't matter for equality...
        foreach( Document d in this.registeredDocuments )
            if( !that.registeredDocuments.Contains(d) )
                return false;
        return true;
    }
    public override int GetHashCode()
    {
        int ret = version.GetHashCode();
        foreach (Document d in this.registeredDocuments)
            ret ^= d.GetHashCode(); // xor isn't great, but better than nothing.
        return ret;
    }
}

注: プロパティが変更を認識している場合、キャッシュは HashCode 値に役立ちます。

于 2012-11-26T19:50:04.003 に答える