2016-05-29 1 views
0

私はカスタムキー構造体を使用してソートされた辞書を持っています。並べ替えを容易にするために、キーに変数をいくつか持たせて、等価比較に参加したいと思います。SortedDictionary.TryGetValue()オーバーロード

クラス

public struct Key 
{ 
    //Needs to participate in equality comparison for SortedDictionary.TryGetValue(); 
    public int intKey; 
    public object objectKey; 

    //Needs to be ignored in SortedDictionary.TryGetValue(); 
    public int sortingVariable; 
    public string otherSortingVariable; 
} 

の例Iは、new Key().equals(new Key())がtrueを返す程度にEqualsGetHashCodeの過負荷を試みました。

しかし、

+0

辞書はどのように作成されましたか?カスタムIComparer をコンストラクタに渡しましたか? – haim770

+0

私はあなたの問題を再現することはできません、私はあなたが説明した 'TryGetValue(new Key()、out Value)'を迅速に実装しようとしましたが、正しい値を返します。 [mcve]を入力してください。 –

+0

@ haim770私は 'Key'が' IComparable 'を実装していることを忘れています。しかし、 'CompareTo'関数はソートのためだけに使用され、' 0'を返すことはありません – DarkDestry

答えて

2

SortedDictionary.TryGetValue(new Key(), out Value)リターンは、あなたが実装されたメソッドは、ソートされた実装で使用されていません。

public struct Key : IComparable<Key> 
{ 
    public int CompareTo(Key other) 
    { 
     return Comparer.Default<string>.Compare(otherSortingVariable, other.otherSortingVariable); 
    } 
} 

またはIComparer<T>インタフェース実装するカスタムクラス:

public class KeyComparer : Comparer<Key> 
{ 
    public override int Compare(Key x, Key y) 
    { 
     return Comparer.Default<string>.Compare(x.otherSortingVariable, y.otherSortingVariable); 
    } 
} 

をし、受け入れSortedDictionaryコンストラクタoverloadに上記のクラスのインスタンスを渡す代わりに、あなたはあなたのstructIComparable<T>インターフェイスを実装するか必要がありますカスタム比較者。

+0

をソートするだけでなく、検索のための比較子を使用していることがわかります。しかし、これは 'TryGetValue'に' CompareTo'を使っているということですか? 'ContainKey'はどうですか?これは、これらの関数の両方が、等しいために返される '0'を必要とすることを意味しますか? – DarkDestry

+0

はい。実際、これは 'SortedDictionary'と前述のメソッドに固有のものではなく、正しい' IComparable'/'IComparer'実装のための要件です。等しい場合は0、小さい場合は0、大きい場合は> 0を返す必要があります。 –

+0

'CompareTo'が0を返さない理由は、ソート変数を比較しているからです。それはキー変数を比較しません。ソート変数は、ソートのためだけに使用され、同じではないことが保証されている独立変数です。それは、鍵に関連付けられたUIDのように考えることができます。UIDは決して同じではありません。ただし、キー変数を使用してリスト内のオブジェクトを識別する必要があります。私は 'Contains'がソートとは何の関係もない等価演算子を使うことを望んでいました。 – DarkDestry

1

あなたSortedDictionaryは完全にあなたが作ったオーバーライドを無視し、平等(see this secion)を決定するためにIComparableインターフェースを使用しているので、あなたはTryGetValueを使用することはできません。ただしLINQのとあなたのEqualsメソッドを使用することができます。

res = dict.Single(kvp => kvp.Key.Equals(comperativeKey)).Value; 

残念ながら、あなたはすべてのパフォーマンス向上をこのように緩いので、それが問題であるならば、あなたはカスタム辞書を持って実装することができます。

Proof of Concept

+0

LINQが時間をO(n)に戻すと仮定しますか? – DarkDestry

+0

Linqが 'Equals'が真を返すまで、すべての要素を列挙するのが簡単なら、線形にスケーリングする必要があります。 –