.net semantics

.net - ¿Cuándo es mejor usar un Tuple versus un KeyValuePair?



semantics (4)

En general, he usado el tipo KeyValuePair<TKey,TValue> siempre que tengo datos relacionados con el par en el sentido de que uno es clave para el otro. Si los datos no están relacionados, entonces el tipo Tuple<T1,T2> tiene más sentido y yo iría con eso.

Ahora acabo de leer este artículo sobre por qué generalmente evito KeyValuePair<TKey,TValue> y prefiero 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> ?


A pesar de la semántica, el rendimiento puede ser una consideración importante al considerar ambas opciones. Como se mencionó anteriormente, KeyValuePair es un tipo de valor (struct), mientras que Tuple<> es un tipo de referencia (clase). Por lo tanto, KeyValuePair se 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 Stack vs. Heap Memory Allocation . En resumen, el espacio de pila es limitado, pero generalmente tiene un acceso muy rápido. La memoria del montón es mucho más grande, pero es algo más lenta.

KeyValuePair<T1, T2> puede ser la mejor opción si tanto la clave como los tipos de valores son primitivos (tipos de valores como int , bool , double , etc.) o estructuras de pequeño tamaño. Con los 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 probablemente la mejor opción si T1 o T2 son tipos de referencia (como clases). Un KeyValuePair que contiene punteros a los tipos de referencia (como la clave o los tipos de valores) en KeyValuePair el propósito, ya que los objetos deberán KeyValuePair 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 tipo de string es un tipo inusual y especial en .NET en el sentido de que puede comportarse como un tipo de valor y / o un tipo de referencia que depende del contexto de ejecución. Creo que KeyValuePair<int, int> hubiera sido un ganador claro contra Tuple<int, int> . Incluso con las deficiencias, sin embargo, los resultados muestran que las diferencias de rendimiento pueden ser significativas:

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

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

1.91 ns - Return Tuple
6.09 ns - Return KeyValuePair

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


Bueno, el tipo podría considerarse mal nombrado, por ejemplo. Un KeyValuePair con el nombre debería representar una clave y un valor. ¿Qué pasa si tus dos objetos no son realmente una llave 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 de KVP fueran una clave y un valor. Esto es solo una cuestión de comunicar la intención y dejarlo en claro en el futuro, o posiblemente en otros miembros del equipo. Una tupla no indica ese tipo de asociación.

Tuples también hace que sea más fácil agregar otro valor, por lo que es una tupla de 3 (o un triplete, como quiera llamarlo). Algunos lenguajes .NET, como F #, también tienen una sintaxis especial alrededor de las tuplas.

Para una perspectiva de implementación, Tuple hace muchas cosas que KeyValuePair no hace. Las tuplas son comparables, implementan las interfaces IComparable y IStructuralEquatable , por lo que es más fácil comparar dos tuplas.


Realmente estás 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é quieres usarlas? Y la respuesta se da aquí. Estructuras versus clases


KeyValuePair es struct y Tuple es 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 usa solo usa "4 bytes" en sistema operativo de 32 bits, mientras que KeyValuePair<K,V> requiere más en función de "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.