Коли краще використовувати Кортеж проти KeyValuePair?


90

Я зазвичай використовував KeyValuePair<TKey,TValue>тип, коли маю дані, пов’язані з парами в тому сенсі, що одне є ключем до іншого. Якщо дані не пов’язані між собою, тоді Tuple<T1,T2>тип має більше сенсу, і я б погодився з цим.

Зараз я просто прочитав цю статтю про те, чому взагалі уникати KeyValuePair<TKey,TValue>та віддавати перевагу Tuple<T1,T2>. Основним аргументом є перевага продуктивності Tuple<T1,T2>.

За межами продуктивності, чи є якась причина, що KVP був би кращим вибором, ніж Tuple<T1,T2>?


4
A KeyValuePair- це ключ і значення, a Tuple<T1,T2>- просто пара рівних значень. Ви також можете запитати: "навіщо мені використовувати a, List<Class>якщо я можу використовувати Dictionary<A,B>".
Тім Шмельтер

4
Правильно, але в такому випадку ви можете використовувати ключ для пошуку даних. Це щось означає. У цьому випадку імена - це лише семантика, вони нічого не означають (для процесора.)
Нік Готч

1
Кортеж - це не пара рівних значень, а деяка кількість рівних типів. Можливо, це розглядається як нікчемність, але, наприклад, C має конструкцію об'єднання для різних подань рівних значень. :)
Йонас,

Відповіді:


65

Ну, тип можна вважати погано названим, наприклад. Пара KeyValuePair за назвою повинна представляти ключ і значення. Що якщо ваші два об’єкти насправді не є ключем і значенням, а лише двома речами? Якби я побачив метод або властивість, що мали тип KeyValuePair<TKey, TValue>, я би очікував, що значення KVP будуть ключем і значенням. Це насправді просто питання передачі намірів та надання чіткого розуміння собі в майбутньому або, можливо, іншим членам команди. Кортеж не означає такого роду асоціації.

Кортежі також полегшують додавання іншого значення, роблячи його 3-кортежним (або триплетним, однак ви хочете його назвати). Деякі мови .NET, такі як F #, також мають спеціальний синтаксис навколо кортежів.

З точки зору реалізації, Tupleбагато речей KeyValuePairне робить цього. Кортежі порівнянні, вони реалізують інтерфейси IComparableі IStructuralEquatable, тому полегшує порівняння двох кортежів.


1
Я зрозумів, що ви можете помістити KeyValuePairs у словник, але ніколи не отримаєте результату тоді.
MKesper

3
Крім того, новий C # 7.0 підтримує новий, простіший синтаксис для Tuples, що робить їх набагато простішими та ефективнішими в роботі з KeyValuePairs. visualstudiomagazine.com/articles/2017/01/01/…
Jacob Stamm

1
Крім того, можливість називати параметри в кортежах полегшує споживачеві зрозуміти, для чого вони повинні використовуватися. У такому загальному вигляді, як KVP, насправді можна здогадуватися - якщо це десь спеціально не задокументовано - яким ключем повинен «бути» - тобто не його тип, а те, що це в реальному світі, як ім’я налаштування, соціальний номер охорони тощо
rory.ap

40

KeyValuePairє структурою і Tupleє класом.

Це основна відмінність, яка впливає на те, як об’єкти копіюються за допомогою посилання чи значень.

і, отже, Tuple<T1,T2>при передачі просто використовує "4 байти" в 32-бітній ОС, тоді як KeyValuePair<K,V>вимагає більше, заснованих на "K і V"

У будь-якому випадку порівняння Tuple і KeyValuePair - це не гарна ідея (для мене це не має сенсу), оскільки обидва вони служать різним цілям.


2
Як вони служать іншим цілям? не могли б ви детальніше це описати.
OldSchool

1
@YakRangi keyvaluepair призначений для використання як контейнер для ключів і значень у словнику, інакше він не служить жодній меті. З іншого боку, Tuple можна використовувати для зберігання будь-яких довільно пов'язаних членів разом. Також за допомогою Tuple ви можете зберігати декілька членів, а не лише 2.
Шрірам Сактивель,

@SriramSakthivel Це означає, що відповідь на питання OP така: не використовуйте KVP, якщо ви не переглядаєте словник.
Алекс Файнштейн

23

Незважаючи на семантику, продуктивність може бути важливим фактором, оскільки ви розглядаєте обидва варіанти. Як уже згадувалося раніше, KeyValuePairце тип значення (struct), тоді як the Tuple<>- тип посилання (клас). Отже, KeyValuePairвиділяється в стеку, а в Tuple<>купі, і оптимальний вибір зазвичай визначається класичними аргументами Stack vs. Heap Memory Allocation . Коротше кажучи, простір стека обмежений, але, як правило, має дуже швидкий доступ. Пам'ять купи значно більша, але дещо повільніша.

KeyValuePair<T1, T2>може бути кращим вибором , якщо як ключ і значення типу примітиви (типу значення , як int, bool, doubleі т.д.) або Структури малого розміру. З примітивними типами в стеку розподіл та вивільнення відбувається блискавично. Це може реально вплинути на продуктивність, особливо як аргументи для викликів рекурсивних методів.

З іншого боку, Tuple<T1, T2> швидше за все, кращий вибір, якщо той T1чи інший T2є посилальними типами (наприклад, класи). А, KeyValuePairяке містить покажчики на типи посилань (як типи ключів або значень), перешкоджає цілі, оскільки об’єкти все одно потрібно буде шукати в купі.

Ось орієнтир, який я знайшов в Інтернеті: Tuple проти KeyValuePair . Єдина проблема з цим тестом полягає в тому, що вони тестували KeyValuePair<string, string>проти Tuple<string, string>, а stringтип є незвичним та особливим типом у .NET, оскільки він може поводитися як тип значення, так і / або тип посилання, залежно від контексту виконання. Я вважаю, що він KeyValuePair<int, int>би був явним переможцем Tuple<int, int>. Однак, навіть маючи недоліки, результати показують, що відмінності в роботі можуть бути значними:

8,23 нс - Виділити кортеж
0,32 нс - Розподілити KeyValuePair (в 25 разів швидше!)

1,93 нс - Передати кортеж як аргумент
2,57 нс - Передати KeyValuePair як аргумент

1,91 нс - зворотний кортеж
6,09 нс - повернення KeyValuePair

2,79 нс - Завантажити кортеж зі списку
4,18 нс - Завантажити KeyValuePair зі списку


0

Ви дійсно задаєте неправильний питання правильне питання з допомогою класу (кортеж) _ краще , ніж Struct (КВП) , в цьому випадку є відповіддю то , що ви хочете використовувати їх , і відповідь дається тут структур по порівнянні з класами


2
Він задав правильне запитання. Питання про те, що краще для якого використання, явно мається на увазі.
Грег

@Greg питання в тому, що краще шоколад чи газована вода, однак конкретне питання безглуздо і краще його розглядати як загальне питання про їжу та напої
MikeT

3
Дефакто питання: "Коли я повинен використовувати Tuples Vs. KeyPairs?". Це законне питання. Я думаю, ви просто затрималися на семантиці слова "краще".
Грег
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.