2011-08-09 17 views
9

私がHashSetで読んだことは、クラスに対してデフォルトの比較者を使用していることです。私は、ハッシュセットに2番目のSporkを追加すると、以下のコードが失敗することを期待しています。私は何が起こっているのかについての私の理解は不完全だと思う。IEquatableを使用するようにHashSetを教えてください?

セット内の値を比較するときに使用するIEqualityComparerインプリメンテーション、またはセットタイプに対してデフォルトのEqualityComparerインプリメンテーションを使用する場合はnullです。

デフォルトの比較機能とは何ですか、どうすれば.Netに自分自身の比較機能を使用させることができますか?

public class Spork : IEquatable<Spork> 
{ 
    public int Id { get; set; } 


    public bool Equals(Spork other) 
    { 
     return other != null && other.Id == this.Id; 
    } 

    public override bool Equals(object obj) 
    { 
     var other = obj as Spork; 
     return other != null && other.Id == this.Id; 
    } 

    public override int GetHashCode() 
    { 
     return Id.GetHashCode(); 
    } 
} 

public class Bjork 
{ 
    public static HashSet<Spork> Sporks { get; set; } 
    public static void Main() 
    { 
     Sporks = new HashSet<Spork>(); 
     Sporks.Add(new Spork() { Id = 0 }); 
     Sporks.Add(new Spork() { Id = 0 });  // come on, please throw an exception 
    } 
} 

答えて

21

それはあなたの平等の方法を使用してである - しかし、あなたは等しい値を追加しようとするHashSet<T>.Addは例外をスローしない - それはちょうどfalseを返します。

最後の2行を変更して戻り値Addを出力すると、初めてTrue、次にFalseを返します。

class UniqueHashSet<T> : HashSet<T>, IEquatable<T> 

すると、当然のことながら、新しいの書き込み:あなたの目標は辞書のように動作し、同じエントリを複数回を禁止し、例外をスローする場合

+2

今私は本当に馬鹿だと感じます。 – Amy

+4

@Inuyasha:必要はありません - 私たちは今までにドキュメントを読むことができませんでした:) –

+0

['HashSet 'ドキュメント](http://msdn.microsoft.com/en-us/library/bb359438(v=vs) .110).aspx)はIEquatableはどこにも言及していないようです。私は何か不足していますか?私は[HashSet がどのようにcomparerを構築するのか](http://referencesource.microsoft.com/#System.Core/System/Collections/Generic/HashSet.cs#106)のリファレンスソースを掘り下げて同じ結論に達しました。デフォルトの比較関数は要素型を調べ、IEquatableを実装する場合はそれを "何とか"使うために_seems_を使います。 – KFL

1

、あなたはHashSetのとIEquatableから継承しなければなりません.Add()ベースを非表示にする方法。

しかし、もっと良い方法があると確信しています。

@Jonは言うとおり、独自のコレクションを維持しています。

関連する問題