2016-01-18 2 views
2

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

var myCrazyDictionary = new Dictionary<List<MyKeyObject>, List<MyValueObject>>(); 

Как такой словарь вести? Вы знаете, из-за ссылочных типов ...

Работает ли она так магически?

// ???? 
myCrazyDictionary.Add(new List<MyKeyObject> { new MyKeyObject { Key1 = "1", Key2 = 2 } }, new List<MyValueObject> { new MyValueObject { Value = "!" } }); 

// ??????????? 
var result = myCrazyDictionary[new List<MyKeyObject> { new MyKeyObject { Key1 = "1", Key2 = 2 } }]; 
// Will this hold the value: "!" or crash or something else? 
var byWhatBlackMagic = result[0].Value; 
+0

Загрузите [LinqPad] (https://www.linqpad.net), разместите там свой код и протестируйте его самостоятельно. Или Visual Studio 2015 имеет интегрированный REPL. –

+0

Вероятно, вы должны написать свой собственный класс для хранения значений ключа. Убедитесь, что ключ не изменяется (в идеале, делая его неизменным). –

ответ

7

Это будет иметь такой же, как если бы вы сделали словарь Dictionary<Object, List<MyValueObject>> и просто сделал new Object() как для дополнения и поиска. List<T> не переопределяет Equals(object) и GetHashCode(), поэтому он просто использует поведение по умолчанию, которое сравнивает только ссылки на объекты. Он не будет выглядеть внутри списка для сравнения. Таким образом, ваш пример будет вызывать KeyNotFoundException, когда вы пытаетесь сделать myCrazyDictionary[new List<MyKeyObject> { ... }], потому что вы создаете «новый объект», и этот новый объект не находится в словаре (потому что вы только что создали его).

Вы можете получить необходимую функциональность, вам просто нужно создать пользовательский IEqualityComparer<List<MyKeyObject>> и передать его в конструктор вашего словаря.

Знайте! Если вы внесете пользовательский сопоставитель в свой List<MyKeyObject>, который связан с вашим обычным Equals(List<MyKeyObject>, List<MyKeyObject>), либо ваш пользовательский .GetHashCode(List<MyKeyObject>) может быть изменен, пока он действует как рулон ключа, или вы нарушите внутреннюю логику Dictionary.

+0

Да, глядя на [исходный код для списка] (https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Collections/Generic/List.cs/), я подтвердил, что 'List ' не переопределяет 'Equals' и' GetHashCode'. – minghan

+2

@minghan Вы также можете проверить [глядя на MSDN] (https://msdn.microsoft.com/en-us/library/6sh2ey19.aspx), если метод переопределен, он скажет «* (переопределяет объект. Equals (Object).) * ", И если он не будет превышен, он скажет: * * (Унаследовано от Object.) *" (См. [MSDN для 'Version'] (https://msdn.microsoft.com/en- us/library/system.version (v = vs.110) .aspx) для примера его переопределения). Проверка источника является «детальностью реализации» и может быть изменена, что-либо на MSDN является «контрактом», и поведение гарантируется, что оно не изменится между версиями .NET, если не указано в примечаниях –

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