Когда лучше использовать Tuple и KeyValuePair?
Обычно я использовал тип KeyValuePair<TKey,TValue>
всякий раз, когда у меня есть данные, которые связаны с парой в том смысле, что один из них является ключом к другому. Если данные не связаны, то тип Tuple<T1,T2>
имеет больше смысла, и я бы пошел с этим.
Теперь я просто прочитал эту статью о том, почему вообще избегать KeyValuePair<TKey,TValue>
и предпочитает Tuple<T1,T2>
. Основным аргументом является преимущество производительности Tuple<T1,T2>
.
Внешняя производительность, есть ли причина, по которой KVP будет лучшим выбором, чем Tuple<T1,T2>
?
Ответы
Ответ 1
Ну, тип можно назвать плохо названным, для одного. KeyValuePair как именованный должен представлять ключ и значение. Что делать, если ваши два объекта не являются ключом и ценностью, всего две вещи? Если бы я увидел метод или свойство, имеющее тип KeyValuePair<TKey, TValue>
, я ожидал бы, что значения KVP будут ключом и значением. Это на самом деле просто вопрос передачи намерения и разъяснения себе в будущем или, возможно, других членов команды. Кортеж не указывает на такую ассоциацию.
Кортежи также упрощают добавление другого значения, делая его 3-кортежем (или триплет, однако вы хотите его называть). Некоторые языки .NET, такие как F #, имеют специальный синтаксис вокруг кортежей.
Для перспективы реализации Tuple
делает много вещей KeyValuePair
. Кортежи сопоставимы, они реализуют интерфейсы IComparable
и IStructuralEquatable
, поэтому упрощается сравнение двух кортежей.
Ответ 2
KeyValuePair
- это struct и Tuple
- класс.
Это основное отличие, которое влияет на то, как объекты копируются по ссылке или значениям.
и, следовательно, Tuple<T1,T2>
при передаче только использует "4 байта" в 32-битной ОС, тогда как KeyValuePair<K,V>
требует больше основанных на "K и V"
В любом случае сравнение Tuple и KeyValuePair - не очень хорошая идея (для меня это не имеет смысла), так как обе служат для разных целей.
Ответ 3
Несмотря на семантику, производительность может быть важным фактором, поскольку вы рассматриваете оба варианта. Как уже упоминалось ранее, KeyValuePair
представляет собой тип значения (struct), тогда как 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 ns - Распределить кортеж
0,32 нс - выделите KeyValuePair (на 25 раз быстрее!)
1.93 ns - передать Tuple в качестве аргумента
2.57 ns - передать KeyValuePair в качестве аргумента
1.91 ns - Возврат кортежа
6.09 ns - Return KeyValuePair
2.79 ns - Загрузка кортежа из списка
4.18 ns - Загрузить KeyValuePair из списка
Ответ 4
В самом деле, задавая неправильный вопрос, правильный вопрос использует класс (кортеж) _ лучше, чем Struct (KVP), и в этом случае ответ - это то, что вы хотите использовать для них, и здесь дается ответ Структуры против классов