2013-02-13 2 views
1

Я пытаюсь использовать Except-Function для SortedDicationary, но я безумный, поскольку он не ведет себя так, как я ожидал. Функция Excpet работает до тех пор, пока записи словаря имеют простой тип данных. Тем не менее, я хотел бы хранить объекты в dictionay.Странное поведение исключающей функции SortedDictionary

Вот мой пример:

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Threading.Tasks; 


namespace DictionaryTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      SortedDictionary<string, Object> objects = new SortedDictionary<string, Object>(); 
      SortedDictionary<string, Object> objects2 = new SortedDictionary<string, Object>(); 




      objects.Add("A", new Object()); 
      objects.Add("B", new Object()); 
      objects2.Add("A", new Object()); 

      IEnumerable<KeyValuePair<string, Object>> objects_a_only = objects.Except(objects2); 

      foreach (KeyValuePair<string, Object> o in objects_a_only) 
      { 
       Console.WriteLine(o.Key); 


      } 
      Console.WriteLine("Program finished. Press any key to continue"); 
      Console.ReadKey(); 


     } 
    } 
} 

Я ожидал получить только «А» в качестве выходного сигнала, но на самом деле возвращает «A» и «B».

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

Любые идеи по этому вопросу?

ответ

1

Except не является методом на SortedDictionary<TKey, TValue>.
Это метод расширения на IEnumerable<T>.
В случае отсортированного словаря T на самом деле KeyValuePair<TKey, TValue>.

Так, Except сравнивает экземпляры KeyValuePair<TKey, TValue>.
Два экземпляра KeyValuePair<TKey, TValue> считаются одинаковыми, если Key и Value - то же самое.
Поскольку каждый раз вы создаете новый экземпляр object, все три экземпляра KeyValuePair<TKey, TValue> считаются не равными друг другу.
Вы можете легко проверить это, изменив свой код на этот:

var o = new object(); 
objects.Add("A", o); 
objects.Add("B", new Object()); 
objects2.Add("A", o); 

Результат objects.Except(objects2) теперь будет только запись с ключом "B".

0

При использовании Enumerable.Except используется сопоставитель равенства по умолчанию, который для типа KeyValuePair сравнивает как ключи, так и значения. Вместо этого вы можете использовать этот подход:

IEnumerable<KeyValuePair<string, Object>> objects_a_only = objects 
     .Where(kvp => !objects2.ContainsKey(kvp.Key)); 
+0

Спасибо за помощь. Я, очевидно, неправильно понял эту структуру данных ... – Norbert

+0

@Norbert: Я предполагаю, что вы просто не заметили, что используете метод расширения 'Enumerable', который создан для каждого типа коллекций, и иногда работает по-другому, как и ожидалось. То же самое произойдет, если вы будете использовать 'Except' в' List ', пока не будете реализовывать' Equals' и 'GetHashCode'. –

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