Когда лучше использовать Tuple вместо KeyValuePair?


90

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

Теперь я просто прочитал эту статью о том, почему вообще следует избегать KeyValuePair<TKey,TValue>и предпочитать Tuple<T1,T2>. Основным аргументом является преимущество в производительности Tuple<T1,T2>.

Помимо производительности, есть ли причина, по которой KVP был бы лучшим выбором, чем KVP Tuple<T1,T2>?


4
A KeyValuePair- это ключ и значение, a Tuple<T1,T2>- это просто пара равных значений. Вы также можете спросить: «Зачем мне использовать, List<Class>если я могу использовать Dictionary<A,B>».
— Тим Шмелтер

4
Верно, но в этом случае вы можете использовать ключ для поиска данных. Это что-то значит. В данном случае имена - это просто семантика, они ничего не значат (для процессора)
— Ник Готч,

1
Кортеж - это не пара равных значений, а некоторое количество равных типов. Может быть, это воспринимается как придирка, но, например, в C действительно есть конструкция union для различных представлений равных значений. :)
— Йонас

Ответы:


65

Ну, например, этот тип можно считать плохо названным. KeyValuePair, как указано, должен представлять ключ и значение. Что, если ваши два объекта на самом деле не ключ и значение, а всего лишь две вещи? Если бы я увидел метод или свойство с типом KeyValuePair<TKey, TValue>, я бы ожидал, что значения KVP будут ключом и значением. На самом деле это просто вопрос передачи намерения и разъяснения его себе в будущем или, возможно, другим членам команды. Кортеж не указывает на такую ​​связь.

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

С точки зрения реализации Tupleмного чего KeyValuePairне делает. Кортеж сравним, они реализуют IComparableи IStructuralEquatableинтерфейсы, так что облегчает сравнение двух кортежей.


1
Я на собственном опыте обнаружил, что вы можете поместить KeyValuePairs в словарь, но тогда никогда не получите результата.
— MKesper 06

3
Кроме того, новый C # 7.0 поддерживает новый, более простой синтаксис для кортежей, что делает их намного проще и производительнее, чем KeyValuePairs. visualstudiomagazine.com/articles/2017/01/01/…
— Джейкоб Штамм,

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это тип значения (структура), тогда как Tuple<>это ссылочный тип (класс). Таким образом, KeyValuePairобъект выделяется в стеке, а объект Tuple<>- в куче, и оптимальный выбор обычно определяется классическими аргументами распределения памяти стека или кучи . Короче говоря, пространство стека ограничено, но обычно имеет очень быстрый доступ. Память кучи намного больше, но работает несколько медленнее.

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

С другой стороны, Tuple<T1, T2>вероятно, лучший выбор, если любой из T1или T2является ссылочными типами (например, классами). A, KeyValuePairкоторый содержит указатели на ссылочные типы (например, типы ключей или значений), как бы побеждает цель, поскольку объекты в любом случае нужно будет искать в куче.

Вот тест, который я нашел в Интернете: Tuple vs. KeyValuePair . Единственная проблема с этим тестом заключается в том, что они тестировали KeyValuePair<string, string>vs. 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

Вы действительно задаете неправильный вопрос, правильный вопрос - это использование Class (Tuple) _ лучше, чем Struct (KVP), и в этом случае ответ - это то, для чего вы хотите их использовать, и ответ дается здесь. Структуры по сравнению с классами


2
Он задал правильный вопрос. Явно подразумевается вопрос, что лучше для какого использования.
— Грег

@Greg, вопрос в том, что лучше шоколад или газировка, однако конкретный вопрос бессмысленен и его лучше решать как общий вопрос о еде и напитках
— MikeT 08

3
Фактически вопрос: «Когда мне следует использовать кортежи или пары ключей?». Это законный вопрос. Я думаю, вы просто зациклились на семантике слова «лучше».
— Грег
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.