Quale requisito è stato progettato per risolvere la tupla?


94

Sto esaminando la nuova funzionalità C # delle tuple. Sono curioso, quale problema è stata progettata per risolvere la tupla?

Per cosa hai usato le tuple nelle tue app?

Aggiornare

Grazie per le risposte finora, fammi vedere se ho le cose a posto. Un buon esempio di tupla è stato indicato come coordinate. Sembra giusto?

var coords = Tuple.Create(geoLat,geoLong);

Quindi usa la tupla in questo modo:

var myLatlng = new google.maps.LatLng("+ coords.Item1 + ", "+ coords.Item2 + ");

È corretto?



4
Beh, posso pensare a due risposte ...
Noon Silk

13
Se il concetto di "coordinate" ha senso come classe, lo farei diventare una classe. Utilizzare tuple per quelle situazioni in cui v'è non un concetto sensato "business logic" per il set di dati che giustifica che fanno un tipo.
Eric Lippert,

13
Le coordinate non sono un buon esempio di tupla. Tuple in C # è solo una soluzione ad hoc nei casi in cui è necessario restituire (da una funzione) due valori. Invece di impostare un tipo di risultato più un parametro out, è più elegante restituire una tupla. In questo modo non è necessario dichiarare in anticipo il secondo parametro. La differenza è ancora più chiara in C ++ (puoi constare il risultato, ma non puoi constare il parametro out / ref).
greenoldman

8
Perché python ce l'aveva e python non può avere nulla che C # non abbia;)
Evan Plaice,

Risposte:


117

Quando si scrivono programmi è estremamente comune voler raggruppare logicamente un insieme di valori che non hanno abbastanza elementi comuni per giustificare la creazione di una classe.

Molti linguaggi di programmazione consentono di raggruppare logicamente un insieme di valori altrimenti non correlati senza creare un tipo in un solo modo:

void M(int foo, string bar, double blah)

Logicamente questo è esattamente lo stesso di un metodo M che accetta un argomento che è una 3-tupla di int, string, double. Ma spero che tu non realizzi effettivamente:

class MArguments
{
   public int Foo { get; private set; } 
   ... etc

a meno che MArguments non avesse un altro significato nella logica aziendale.

Il concetto di "raggruppare un mucchio di dati altrimenti non correlati in una struttura che è più leggera di una classe" è utile in molti, molti posti, non solo per elenchi di parametri formali di metodi. È utile quando un metodo ha due cose da restituire o quando si desidera escludere un dizionario da due dati anziché uno, e così via.

Linguaggi come F # che supportano i tipi di tupla in modo nativo forniscono una grande flessibilità ai propri utenti; sono un insieme estremamente utile di tipi di dati. Il team BCL ha deciso di collaborare con il team F # per standardizzare un tipo di tupla per il framework in modo che ogni linguaggio potesse trarne vantaggio.

Tuttavia, a questo punto non è disponibile alcun supporto linguistico per le tuple in C #. Le tuple sono solo un altro tipo di dati come qualsiasi altra classe di framework; non c'è niente di speciale in loro. Stiamo valutando l'aggiunta di un supporto migliore per le tuple in ipotetiche versioni future di C #. Se qualcuno ha qualche idea sul tipo di funzionalità che coinvolgono le tuple che vorresti vedere, sarei felice di trasmetterle al team di progettazione. Gli scenari realistici sono più convincenti delle riflessioni teoriche.


1
@MalcomTucker: Asychrony e parallelismo sono sicuramente nelle nostre menti come aree ricche in cui gli strumenti linguistici potrebbero essere utilizzati per risolvere problemi reali. Non penso che i flussi di lavoro asincroni in stile F # siano necessariamente la soluzione migliore per C #, ma sono sicuramente stimolanti.
Eric Lippert,

60
Sebbene le tuple siano utili, un grosso svantaggio è la chiarezza. È difficile leggere e comprendere il codice che fa riferimento a Item1, Item2ecc ... Se le tuple raggiungono mai il supporto del linguaggio in C #, sarebbe meraviglioso consentire ai loro membri di essere denominati (o almeno con alias) in un modo che consente il codice che utilizza per essere più comprensibili. In un futuro così ipotetico, mi piacerebbe anche vedere tuple di "forma" appropriata come parametri legali per metodi che accettano parametri individuali (e viceversa). Quindi, Tuple<int,string,bool>può essere passato a M(int,string,bool). Renderebbe molto più semplici i metodi di memorizzazione.
LBushkin

2
Queste "tuple" sono fondamentalmente tutti tipi anonimi dipublic accesso con membri senza nome . Preferirei che il programmatore scrivesse un con membri nominati e lo restituisse, piuttosto che avere a che fare con un che non mi dice nulla sulla semantica dei suoi membri. structstructtuple
bobobobo

1
@ Hi-Angel: L'argomento non riguarda il cavillare su ciò che conta come tupla e cosa no, ma piuttosto su quale sia il set di funzionalità che i moderni sviluppatori line-of-business potrebbero utilizzare per aumentare la loro produttività . LBushkin esprime una richiesta di funzionalità che il team di progettazione sente continuamente: il desiderio di fare un "tipo di record" di qualche tipo senza la fatica e la spesa di creare un'intera classe solo per tenere insieme alcuni campi. C # dispone già di questa funzionalità per i metodi; si chiama "lista dei parametri".
Eric Lippert

2
@ Hi-Angel: probabilmente non faresti l'argomento "se vuoi accedere ai parametri del tuo metodo per nome, dovresti creare una classe separata" perché sembra estremamente pesante, ma sembra pesante solo perché siamo abituati ad avere il capacità di legare insieme istantaneamente un insieme di variabili arbitrarie con tipi e nomi arbitrari quando si chiama un metodo . Immagina che nessuna lingua avesse quella caratteristica; ogni metodo può richiedere solo un singolo argomento e se si desidera passarne due, è necessario creare un tipo e passarne un'istanza.
Eric Lippert

22

Le tuple forniscono un'implementazione immutabile di una raccolta

A parte gli usi comuni delle tuple:

  • per raggruppare valori comuni senza dover creare una classe
  • per restituire più valori da una funzione / metodo
  • eccetera...

Gli oggetti immutabili sono intrinsecamente thread-safe:

Gli oggetti immutabili possono essere utili nelle applicazioni multi-thread. Più thread possono agire sui dati rappresentati da oggetti immutabili senza preoccuparsi che i dati vengano modificati da altri thread. Gli oggetti immutabili sono quindi considerati più thread-safe rispetto agli oggetti mutabili.

Da "Oggetto immutabile" su wikipedia


Grazie per aver aggiunto ulteriori informazioni alla domanda. Molto apprezzato.
Chaddeus

Se vuoi una raccolta immutabile, dovresti usare una raccolta immutabile, non una tupla. La differenza è che per la maggior parte delle raccolte immutabili non è necessario specificare il numero di elementi in fase di compilazione
BlueRaja - Danny Pflughoeft

@ BlueRaja-DannyPflughoeft Quando ho scritto questa risposta, le classi di raccolta immutabili C # non erano ancora disponibili nel BCL. Immagino che cambierò 'collection' in 'object' poiché MS ha neutralizzato l'implementazione di Tuple in C #
Evan Plaice

12

Fornisce un'alternativa refo outse si dispone di un metodo che deve restituire più nuovi oggetti come parte della sua risposta.

Ti consente anche di utilizzare un tipo incorporato come tipo restituito se tutto ciò che devi fare è mescolare due o tre tipi esistenti e non vuoi dover aggiungere una classe / struttura solo per questa combinazione. (Hai mai desiderato che una funzione restituisse un tipo anonimo? Questa è una risposta parziale a quella situazione.)


Dannazione. Bello. Vorrei aver controllato cosa sono le tuple qualche anno fa;).
sabiland



4

Personalmente, trovo che le tuple siano una parte iterativa dello sviluppo quando sei in un ciclo investigativo, o semplicemente "giocando". Poiché una tupla è generica, tendo a pensarci quando lavoro con parametri generici, specialmente quando voglio sviluppare una parte di codice generica e sto iniziando dalla fine del codice, invece di chiedermi "come vorrei questa chiamata guardare?".

Molto spesso mi rendo conto che la raccolta che forma la Tupla diventa parte di una lista, e fissare List> non esprime realmente l'intenzione della lista, o come funziona. Spesso "convivo" con esso, ma mi ritrovo a voler manipolare l'elenco e cambiare un valore - a quel punto, non voglio necessariamente creare una nuova tupla per quello, quindi ho bisogno di creare la mia classe o struttura per tenerlo, così posso aggiungere il codice di manipolazione.

Ovviamente ci sono sempre metodi di estensione, ma molto spesso non si desidera estendere quel codice extra a implementazioni generiche.

Ci sono state volte in cui volevo esprimere i dati come una tupla e non avevo tuple disponibili. (VS2008), nel qual caso ho appena creato la mia classe Tuple e non la rendo thread-safe (immutabile).

Quindi immagino di essere dell'opinione che le tuple siano una programmazione pigra a scapito della perdita di un nome di tipo che ne descriva lo scopo. L'altra spesa è che devi dichiarare la firma della tupla ovunque sia usata come parametro. Dopo una serie di metodi che iniziano a sembrare gonfi, potresti sentire come me che vale la pena creare una classe, poiché ripulisce le firme dei metodi.

Tendo a iniziare con la classe come membro pubblico della classe in cui stai già lavorando. Ma nel momento in cui si estende oltre una semplice raccolta di valori, ottiene il suo file e lo sposto dalla classe contenente.

Quindi, in retrospettiva, credo di usare le tuple quando non voglio uscire e scrivere una lezione, e voglio solo pensare a quello che sto scrivendo in questo momento. Il che significa che la firma della tupla può cambiare parecchio nel testo mezz'ora mentre cerco di capire di quali dati avrò bisogno per questo metodo e come restituirà i valori che restituirà.

Se ho la possibilità di effettuare il refactoring del codice, spesso metto in dubbio il posto di una tupla al suo interno.


3

Vecchia domanda dal 2010, e ora nel 2017 Dotnet cambia e diventa più intelligente.

C # 7 introduce il supporto del linguaggio per le tuple, che abilita i nomi semantici per i campi di una tupla usando tipi di tupla nuovi e più efficienti.

In vs 2017 e .Net 4.7 (o installando il pacchetto nuget System.ValueTuple), è possibile creare / utilizzare una tupla in un modo molto efficiente e semplice:

     var person = (Id:"123", Name:"john"); //create tuble with two items
     Console.WriteLine($"{person.Id} name:{person.Name}") //access its fields

Restituzione di più di un valore da un metodo:

    public (double sum, double average) ComputeSumAndAverage(List<double> list)
    {
       var sum= list.Sum();
        var average = sum/list.Count;
        return (sum, average);
    }

    How to use:

        var list=new List<double>{1,2,3};
        var result = ComputeSumAndAverage(list);
        Console.WriteLine($"Sum={result.sum} Average={result.average}");    

Per maggiori dettagli leggi: https://docs.microsoft.com/en-us/dotnet/csharp/tuples


1

Una tupla viene spesso utilizzata per restituire più valori dalle funzioni quando non si desidera creare un tipo specifico. Se hai familiarità con Python, Python lo ha avuto per molto tempo.


1

Restituzione di più di un valore da una funzione. getCoordinates () non è molto utile se restituisce solo x o y o z, ma anche creare una classe completa e un oggetto per contenere tre int sembra piuttosto pesante.


1

Un uso comune potrebbe essere quello di evitare di creare classi / strutture che contengono solo 2 campi, invece di creare una tupla (o una KeyValuePair per ora). Utile come valore di ritorno, evita di passare N parametri ...


0

Trovo che KeyValuePair si aggiorni in C # per iterare sulle coppie di valori chiave in un dizionario.


KeyValuePairpuò essere visto come una soluzione alternativa speciale. In Python, l'iterazione su dicttuple restituisce (chiave, valore).
dan04

Sì, come il pitone. :-) Non sapevo che KeyValuePair in c # non fosse una tupla?
Jubal

0

È davvero utile durante la restituzione dei valori dalle funzioni. Possiamo avere più valori indietro e questo è un bel risparmio in alcuni scenari.


0

Mi sono imbattuto in questo benchmark delle prestazioni tra tuple e coppie chiave-valore e probabilmente lo troverai interessante. In sintesi si dice che Tuple ha un vantaggio perché è una classe, quindi è memorizzata nell'heap e non nello stack e quando viene passato come argomento il suo puntatore è l'unica cosa che sta andando. Ma KeyValuePair è una struttura quindi è più veloce da allocare ma è più lento quando viene utilizzato.

http://www.dotnetperls.com/tuple-keyvaluepair

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.