2011-08-09 20 views
19

私は主に、私はこのような何かを持って、辞書のキーとしてカスタムオブジェクトを使用したい:使用カスタムオブジェクトとして辞書のキー

class Tuple<A, B> : IEquatable<Tuple<A,B>> 
{ 
    public A AValue { get; set; } 
    public B BValue { get; set; } 

    public Tuple(A a, B b){ AValue = a; BValue = b; } 

    public bool Equals(Tuple<A, B> tuple) 
    { 
    return tuple.AValue.Equals(AValue) && tuple.BValue.Equals(BValue); 
    } 

    public bool Equals(object o) 
    { 
    return this.Equals(o as Tuple<A,B>); 
    } 
} 
(私はそう、私はタプルを持っていない.NET 4.0を使用することはできません)

私はこのようなことをします。

var boolmap = new Dictionary<Tuple<bool, bool>, string>(); 
    boolmap.Add(new Tuple<bool,bool>(true, true), "A"); 
    boolmap.Add(new Tuple<bool,bool>(true, false), "B"); 
    boolmap.Add(new Tuple<bool,bool>(false, true), "C"); 
    boolmap.Add(new Tuple<bool,bool>(false, false), "D"); 
    var str = boolmap[new Tuple<bool,bool>(true, false)]; 

最後の行にKeyNotFound例外が発生します。どうしてこれなの ?私はIEquatableを実装するだけで十分ですか?あなたはEqualsメソッドをオーバーライドするときGetHashCodeをオーバーライドする必要が

おかげ

+1

getハッシュコードの実装はどこですか?あなたがあなたのパースを平等にするならば、常にハッシュコードを取得するべきです – Manatherin

+7

あなたのコードはあなたに警告を出します。その警告を修正すると別の警告が表示され、修正するとコードが機能します。警告を無視しないでください。 –

+0

あなたは見たことがあります:[オブジェクトを使用して汎用辞書としてキーをネットで](http:// stackoverflow。com/questions/634826/generic-dictionary-key-in-netとしてオブジェクトを使用する) – nawfal

答えて

29

またGetHashCode()(および好ましくはまたEquals())をオーバーライドする必要があります。そうでなければ等しいオブジェクトが別のハッシュコードを返しています。これは、ルックアップ時にキーが見つからないことを意味します。

GetHashCode()コントラクトでは、2つのオブジェクトが等しいと見なされたときに、2つのオブジェクトの戻り値が等しい必要があります。これが問題の根本です。あなたのクラスはこの要件を満たしていません。契約では、値が等しくなければ値が異なる必要があるとは指定されていませんが、これによりパフォーマンスが向上します。 (すべてのオブジェクトが同じハッシュコードを返した場合、あなたにもパフォーマンスの観点から、フラットなリストを使用することができます。)

あなたのケースでは、単純な実装は次のようになります。それは可能性があることを

public override int GetHashCode() 
{ 
    return AValue.GetHashCode()^BValue.GetHashCode(); 
} 

注意AValueまたはBValuenullであるかどうかをテストすることをお勧めします。 (あなたがジェネリック型ABを制約していないので、あなただけのnullに値を比較することはできませんので、これは、多少複雑になります - 。たとえば、型は値型することができる)

は、それはまたですディクショナリキーとして使用するクラスを不変にすることをお勧めします。キーとして使用されているオブジェクトの値を変更すると、そのオブジェクトは属していないバケットにあるので、辞書は奇妙な動作を示します。それがnullチェックの必要性を排除するよう、あなたが、ここでEqualityComparer<A>.Default.GetHashCode(AValue)の使用(およびBValueについても同様)を作ることができ


注意。

+0

オブジェクトを正しく動作させるためには、非常に重要なMANDATORYルールセットがあります。辞書内。 [Implementing Equals()](http://geekswithblogs.net/gmamaladze/archive/2010/11/27/implementing-the-equals-method-in-.net-and-linear-algebra.aspx) [Equals()を実装しているMSDN](http://msdn.microsoft.com/en-us/library/336aedhh.aspx) –

+1

もう1つの優れたリファレンスはhttp://blogs.msdn.com/b/ericlippert/archive /2011/02/28/guidelines-and-rules-for-gethashcode.aspx – LukeH

0

GetHashCode関数をオーバーライドしていましたが、GetHashCodeが同じ値を返しても、更新は行われていないようです。 Equalsを持っていても、すべてが面白いです。

関連する問題