2016-05-29 2 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; 
} 

Я попытался перегрузки Equals и GetHashCode в той степени, что new Key().equals(new Key()) возвращает истинное.

Однако SortedDictionary.TryGetValue(new Key(), out Value) возвращает ложные

+0

Как был создан словарь? Вы передали конструктор 'IComparer ' конструктору? – haim770

+0

Я не могу воссоздать вашу проблему, я попытался быстро реализовать то, что вы описали, и 'TryGetValue (новое значение Key(), out Value) возвращает правильное значение. Пожалуйста, предоставьте [mcve]. –

+0

@ haim770 Я забыл указать, что 'Key' реализует' IComparable '. Однако функция 'CompareTo' используется исключительно для сортировки и никогда не вернется '0' – DarkDestry

ответ

2

Методы, реализованные не используются отсортированных реализаций. Вместо этого вам необходимо либо реализовать IComparable<T> интерфейс в вашем struct:

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, который принимает изготовленный под заказ сопоставитель.

+0

Я забыл указать, что я уже реализовал это. Но означает ли это, что он использует 'CompareTo' в' TryGetValue'? Как насчет 'ContainKey'? Означает ли это, что обе эти функции требуют, чтобы «0» было возвращено, чтобы оно было равным? – DarkDestry

+0

Да. На самом деле это не специфично для 'SortedDictionary' и вышеперечисленных методов, а является требованием для правильной реализации' IComparable'/'IComparer'. Вы должны вернуть 0 для равных, <0 для меньше и> 0 для большего. –

+0

Причина, по которой «CompareTo» не возвращает 0, состоит в том, что она сравнивает переменные сортировки. Он не сравнивает ключевые переменные. Переменная сортировки представляет собой некоторую независимую переменную, которая используется исключительно для сортировки и гарантированно не будет одинаковой. Подумайте, как UID, связанный с ключом.UID никогда не будет прежним. Тем не менее, мне все еще нужно идентифицировать объект в списке, используя ключевые переменные. Я надеялся, что «Содержит» использует операторы равенства, которые не имеют ничего общего с сортировкой. – DarkDestry

1

Поскольку ваш SortedDictionary полностью игнорирует переопределение сделанные вами и использует интерфейс IComparable для определения равенства (see this secion) вы не можете использовать TryGetValue. Однако вы можете использовать метод Equals с Linq:

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

К сожалению, вы потеряете весь прирост производительности таким образом, так что если это вопрос, вы можете реализовать у вас есть пользовательский словарь.

Proof of Concept

+0

Я предполагаю, что LINQ возвращает время назад к O (n)? – DarkDestry

+0

Я так думаю, если Linq просто перечисляет все элементы, пока 'Equals' не вернет true, он должен масштабироваться линейно. –

Смежные вопросы