Когда лучше использовать 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интерфейсы, так что облегчает сравнение двух кортежей.

vcsjones
источник
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), и в этом случае ответ - это то, для чего вы хотите их использовать, и ответ дается здесь. Структуры по сравнению с классами

MikeT
источник
2
Он задал правильный вопрос. Явно подразумевается вопрос, что лучше для какого использования.
Грег
@Greg, вопрос в том, что лучше шоколад или газировка, однако конкретный вопрос бессмысленен и его лучше решать как общий вопрос о еде и напитках
MikeT 08
3
Фактически вопрос: «Когда мне следует использовать кортежи или пары ключей?». Это законный вопрос. Я думаю, вы просто зациклились на семантике слова «лучше».
Грег