¿Cuándo es mejor usar una tupla en lugar de un KeyValuePair?

90

Por lo general, utilizo el KeyValuePair<TKey,TValue>tipo siempre que tengo datos relacionados con pares en el sentido de que uno es la clave del otro. Si los datos no están relacionados, entonces el Tuple<T1,T2>tipo tiene más sentido y yo iría con eso.

Ahora acabo de leer este artículo sobre por qué generalmente evitar KeyValuePair<TKey,TValue>y preferir Tuple<T1,T2>. El argumento principal es el beneficio de rendimiento de Tuple<T1,T2>.

Rendimiento externo, ¿hay alguna razón por la que un KVP sea una mejor opción que un Tuple<T1,T2>?

Nick Gotch
fuente
4
A KeyValuePaires una clave y un valor, a Tuple<T1,T2>es solo un par de valores iguales . También puede preguntar: "¿Por qué debería usar un List<Class>si puedo usarlo? Dictionary<A,B>".
Tim Schmelter
4
Correcto, pero en ese caso puedes usar la clave para buscar datos. Significa algo. En este caso, los nombres son solo semánticos, no significan nada (para el procesador)
Nick Gotch
1
Una tupla no es un par de valores iguales, sino un número de tipos iguales. Tal vez esto se vea como quisquilloso, pero por ejemplo, C tiene la construcción de unión para diferentes representaciones de valores iguales. :)
Jonas

Respuestas:

65

Bueno, el tipo podría considerarse mal nombrado, por ejemplo. Un KeyValuePair como se indica debe representar una clave y un valor. ¿Qué pasa si sus dos objetos no son realmente una clave y un valor, solo dos cosas? Si tuviera que ver un método o propiedad que tuviera un tipo de KeyValuePair<TKey, TValue>, esperaría que los valores del KVP fueran una clave y un valor. En realidad, esto es solo una cuestión de comunicar la intención y dejarlo claro para usted mismo en el futuro, o posiblemente para otros miembros del equipo. Una tupla no indica ese tipo de asociación.

Las tuplas también facilitan la adición de otro valor, lo que lo convierte en una tupla de 3 (o un triplete, como quieras llamarlo). Algunos lenguajes .NET, como F #, también tienen una sintaxis especial alrededor de las tuplas.

Para una perspectiva de implementación, Tuplehace muchas cosas KeyValuePairque no. Las tuplas son comparables, implementan las interfaces IComparabley IStructuralEquatable, por lo que es más fácil comparar dos tuplas.

vcsjones
fuente
1
Descubrí por las malas que puedes poner KeyValuePairs en un diccionario, pero nunca obtendrás un resultado en ese momento.
MKesper
3
Además, el nuevo C # 7.0 admite una sintaxis nueva y más simple para Tuples, lo que hace que sea mucho más fácil y eficaz trabajar con ellos que KeyValuePairs. visualstudiomagazine.com/articles/2017/01/01/…
Jacob Stamm
1
Además, la capacidad de nombrar los parámetros en tuplas facilita que el consumidor comprenda para qué se supone que deben usarse. En un genérico como KVP, es una incógnita, a menos que esté específicamente documentado en alguna parte, qué se supone que "es" la clave, es decir, no su tipo, sino qué cosa del mundo real es, como un nombre de configuración, número de seguridad, etc.
rory.ap
40

KeyValuePaires estructura y Tuplees una clase.

Esa es la principal diferencia que influye en cómo se copian los objetos, ya sea por referencia o por valores.

y, por lo tanto, Tuple<T1,T2>cuando se transmite solo usa "4byte" en el sistema operativo de 32 bits, mientras que KeyValuePair<K,V>requiere más basado en "K y V"

De todos modos, comparar Tuple y KeyValuePair no es una buena idea (no tiene sentido para mí) ya que ambos tienen un propósito diferente.

Sriram Sakthivel
fuente
2
¿Cómo sirven para un propósito diferente? ¿Podría explicarlo más?
OldSchool
1
@YakRangi keyvaluepair está destinado a ser utilizado como un contenedor de claves y valores en un diccionario, de lo contrario, no tiene ningún propósito. Por otro lado, Tuple se puede utilizar para almacenar juntos cualquier miembro relacionado arbitrariamente. También con Tuple puedes almacenar varios miembros combinados no solo 2.
Sriram Sakthivel
@SriramSakthivel Esto significa que la respuesta a la pregunta de OP es: no use KVP, a menos que esté navegando en un Diccionario.
Alex Fainshtein
23

A pesar de la semántica, el rendimiento puede ser una consideración importante al considerar ambas opciones. Como se mencionó anteriormente, KeyValuePaires un tipo de valor (estructura), mientras que Tuple<>es un tipo de referencia (clase). Por lo tanto, KeyValuePairse asigna en la pila y Tuple<>se asigna en el montón, y la elección óptima suele estar determinada por los argumentos clásicos de asignación de memoria de pila frente a montón . En resumen, el espacio de la pila es limitado, pero generalmente tiene un acceso muy rápido. La memoria del montón es mucho más grande pero algo más lenta.

KeyValuePair<T1, T2>puede ser la mejor opción si tanto la clave y valor tipos son primitivas (tipos de valor como int, bool, double, etc.) o estructuras de pequeño tamaño. Con tipos primitivos en la pila, la asignación y la desasignación son muy rápidas. Esto realmente puede afectar el rendimiento, especialmente como argumentos para llamadas a métodos recursivos.

Por otro lado, Tuple<T1, T2>es probable que sea la mejor opción si T1o T2son tipos de referencia (como clases). Un KeyValuePairque contiene punteros a tipos de referencia (como los tipos de clave o valor) en cierto modo frustra el propósito, ya que los objetos deberán buscarse en el montón de todos modos.

Aquí hay un punto de referencia que encontré en línea: Tuple vs. KeyValuePair . El único problema con este punto de referencia es que probaron KeyValuePair<string, string>vs. Tuple<string, string>, y el stringtipo es un tipo inusual y especial en .NET, ya que puede comportarse como un tipo de valor y / o un tipo de referencia dependiendo del contexto de ejecución. Creo que el KeyValuePair<int, int>hubiera sido un claro ganador en contra Tuple<int, int>. Sin embargo, incluso con las deficiencias, los resultados muestran que las diferencias de rendimiento pueden ser significativas:

8.23 ns - Asignar tupla
0.32 ns - Asignar KeyValuePair (¡25 veces más rápido!)

1.93 ns - Pasa Tuple como argumento
2.57 ns - Pasa KeyValuePair como argumento

1.91 ns - Tupla de retorno
6.09 ns - Devolver KeyValuePair

2.79 ns - Cargar tupla de la lista
4.18 ns - Cargar KeyValuePair de la lista

Salsa especial
fuente
0

Realmente está haciendo la pregunta incorrecta, la pregunta correcta es usar una clase (tupla) _ mejor que una estructura (KVP), en cuyo caso la respuesta es para qué desea usarlos y la respuesta se da aquí Estructuras versus clases

MikeT
fuente
2
Hizo la pregunta correcta. La cuestión de cuál es mejor para qué uso está implícitamente implícita.
Greg
@Greg, la pregunta es cuál es mejor chocolate o refresco, sin embargo, la pregunta específica no tiene sentido y se aborda mejor como una pregunta general sobre alimentos y bebidas
MikeT
3
La pregunta de facto es "¿Cuándo debería usar Tuples Vs. KeyPairs?". Es una pregunta legítima. Creo que estás atrapado en la semántica de la palabra "mejor".
Greg