Quando è meglio usare una tupla rispetto a una KeyValuePair?


91

In genere ho usato il KeyValuePair<TKey,TValue>tipo ogni volta che ho dati relativi alla coppia, nel senso che uno è la chiave per l'altro. Se i dati non sono correlati, il Tuple<T1,T2>tipo ha più senso e lo sceglierei.

Ora ho appena letto questo articolo sul perché in generale evitare KeyValuePair<TKey,TValue>e preferire Tuple<T1,T2>. L'argomento principale è il vantaggio in termini di prestazioni Tuple<T1,T2>.

Al di fuori delle prestazioni, c'è qualche motivo per cui un KVP sarebbe una scelta migliore di un Tuple<T1,T2>?


4
A KeyValuePairè una chiave e un valore, a Tuple<T1,T2>è solo una coppia di valori uguali . Potresti anche chiedere: "perché dovrei usare a List<Class>se posso usare Dictionary<A,B>".
Tim Schmelter

4
Giusto, ma in quel caso puoi usare la chiave per cercare i dati. Significa qualcosa. In questo caso, i nomi sono solo semantici, non significano nulla (per il processore.)
Nick Gotch

1
Una tupla non è una coppia di valori uguali, ma un certo numero di tipi uguali. Forse questo è visto come pignolo, ma ad esempio C ha il costrutto di unione per diverse rappresentazioni di valori uguali. :)
Jonas

Risposte:


68

Ebbene, il tipo potrebbe essere considerato mal chiamato, per esempio. Un KeyValuePair come denominato dovrebbe rappresentare una chiave e un valore. E se i tuoi due oggetti non fossero realmente una chiave e un valore, ma solo due cose? Se dovessi vedere un metodo o una proprietà che aveva un tipo di KeyValuePair<TKey, TValue>, mi aspetto che i valori del KVP siano una chiave e un valore. Questa è davvero solo una questione di comunicare l'intenzione e renderla chiara a te stesso in futuro, o forse ad altri membri del team. Una tupla non indica quel tipo di associazione.

Le tuple rendono anche più facile aggiungere un altro valore, rendendolo una tupla di 3 (o una terzina, comunque tu voglia chiamarla). Alcuni linguaggi .NET, come F #, hanno anche una sintassi speciale per le tuple.

Per una prospettiva di implementazione, Tuplemolte cose KeyValuePairnon lo fanno. Le tuple sono confrontabili, implementano le interfacce IComparablee IStructuralEquatable, quindi è più semplice confrontare due tuple.


1
Ho scoperto a mie spese che puoi mettere KeyValuePairs in un dizionario ma non otterrai mai un risultato allora.
MKesper

3
Inoltre, il nuovo C # 7.0 supporta una nuova sintassi più semplice per le tuple, rendendole molto più facili ed efficienti con cui lavorare rispetto a KeyValuePairs. visualstudiomagazine.com/articles/2017/01/01/…
Jacob Stamm

1
Inoltre, la possibilità di nominare i parametri in tuple rende più facile per il consumatore capire per cosa dovrebbero essere usati. In un generico come KVP, è davvero chiunque indovina - a meno che non sia specificatamente documentato da qualche parte - quale dovrebbe essere la chiave - cioè non il suo tipo ma quale cosa è del mondo reale, come un nome di impostazione, un social numero di sicurezza, ecc.
rory.ap

40

KeyValuePairè struct ed Tupleè una classe.

Questa è la principale differenza che influenza il modo in cui gli oggetti vengono copiati sia per riferimento che per valori.

e quindi Tuple<T1,T2>quando viene passato usa solo "4byte" nel sistema operativo a 32 bit, mentre KeyValuePair<K,V>richiede di più basato su "K e V"

Comunque confrontare Tuple e KeyValuePair non è una buona idea (non ha senso per me) poiché entrambi hanno uno scopo diverso.


3
Come servono a uno scopo diverso? la prego di approfondirlo.
OldSchool

2
@YakRangi keyvaluepair è pensato per essere utilizzato come contenitore per chiavi e valori in un dizionario, altrimenti non serve. D'altra parte Tuple può essere usato per memorizzare insieme qualsiasi membro arbitrariamente correlato. Inoltre con Tuple puoi memorizzare più membri combinati non solo 2.
Sriram Sakthivel

1
@SriramSakthivel Ciò significa che la risposta alla domanda OP è: non usare KVP, a meno che tu non stia sfogliando un dizionario.
Alex Fainshtein

24

Nonostante la semantica, le prestazioni possono essere una considerazione importante se si considerano entrambe le opzioni. Come accennato in precedenza, il KeyValuePairè un tipo di valore (struct), mentre il Tuple<>è un tipo di riferimento (classe). Pertanto, il KeyValuePairè allocato sullo stack e il Tuple<>è allocato sull'heap, e la scelta ottimale è solitamente determinata dai classici argomenti di Stack vs Heap Memory Allocation . In breve, lo spazio dello stack è limitato, ma generalmente ha un accesso molto veloce. La memoria heap è molto più grande ma è leggermente più lenta.

KeyValuePair<T1, T2>può essere la scelta migliore se sia la chiave e il valore tipi sono primitive (tipi di valore preferito int, bool, double, ecc) o strutture di piccole dimensioni. Con i tipi primitivi in ​​pila, l'allocazione e la deallocazione sono velocissime. Questo può davvero influire sulle prestazioni, soprattutto come argomenti per chiamate di metodi ricorsive.

D'altra parte, Tuple<T1, T2>è probabilmente la scelta migliore se uno T1o due T2sono tipi di riferimento (come le classi). Un tipo KeyValuePairche contiene puntatori a tipi di riferimento (come i tipi di chiave o valore) vanifica lo scopo poiché gli oggetti dovranno essere cercati comunque nell'heap.

Ecco un benchmark che ho trovato online: Tuple vs. KeyValuePair . L'unico problema con questo benchmark che hanno testato KeyValuePair<string, string>contro Tuple<string, string>, e il stringtipo è un tipo insolito e speciale in NET in quanto può comportarsi sia come un tipo di valore e / o un tipo di riferimento a seconda del contesto di esecuzione. Credo che KeyValuePair<int, int>sarebbe stato un chiaro vincitore contro Tuple<int, int>. Anche con le carenze, tuttavia, i risultati mostrano che le differenze di prestazioni possono essere significative:

8.23 ns - Alloca tupla
0.32 ns - Alloca KeyValuePair ( 25 volte più veloce!)

1.93 ns - Passa Tuple come argomento
2.57 ns - Passa KeyValuePair come argomento

1.91 ns - Restituisci tupla
6.09 ns - Restituisci KeyValuePair

2.79 ns - Carica tupla dalla lista
4.18 ns - Carica KeyValuePair dalla lista


0

Stai davvero facendo la domanda sbagliata la domanda corretta sta usando una classe (tupla) _ meglio di una struttura (KVP) nel qual caso la risposta è per cosa vuoi usarli e la risposta è data qui Strutture rispetto alle classi


2
Ha fatto la domanda giusta. La domanda su quale sia il migliore per quale utilizzo è esplicitamente implicita.
Greg

@ Greg la domanda è quale sia la migliore cioccolata o soda, tuttavia la domanda specifica è inutile e meglio affrontata come domanda generale su cibo e bevande
MikeT

3
La domanda di fatto è "Quando dovrei usare Tuples Vs. KeyPairs?". È una domanda legittima. Penso che tu sia solo bloccato sulla semantica della parola "meglio".
Greg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.