Domanda

.Net 3.5 non supporta le tuple. Peccato, ma non sei sicuro se la futura versione di .net supporterà le tuple o no?

È stato utile?

Soluzione

Ho appena letto questo articolo dalla rivista MSDN: Building Tuple

Ecco alcuni estratti:

  

La prossima versione 4.0 di Microsoft   .NET Framework introduce un nuovo tipo   chiamato System.Tuple. System.Tuple è a   raccolta a dimensione fissa di   dati tipizzati in modo eterogeneo.   nbsp &;   nbsp &;

nbsp &;

  

Come un array, una tupla ha un valore fisso   dimensione che non può essere cambiata una volta che ha   stato creato. A differenza di un array, ciascuno   L'elemento in una tupla può essere diverso   digitare e una tupla è in grado di garantire   tipizzazione forte per ogni elemento.

nbsp &;

  

Esiste già un esempio di a   tupla fluttuante attorno a Microsoft   .NET Framework, in   Spazio dei nomi System.Collections.Generic:   KeyValuePair. Mentre KeyValuePair può essere pensato come lo stesso   come Tupla, dal momento che sono entrambi   tipi che contengono due cose,   KeyValuePair è diverso da   Tupla perché evoca una relazione   tra i due valori che memorizza (e   con una buona ragione, in quanto supporta il   Classe del dizionario).

     

Inoltre, le tuple possono essere arbitrariamente   dimensioni, mentre KeyValuePair detiene solo   due cose: una chiave e un valore.


Mentre alcune lingue come F # hanno una sintassi speciale per le tuple, puoi usare il nuovo tipo di tupla comune da qualsiasi lingua. Rivisitando il primo esempio, possiamo vedere che, sebbene utili, le tuple possono essere eccessivamente dettagliate nelle lingue senza sintassi per una tupla:

class Program {
    static void Main(string[] args) {
        Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
        PrintStringAndInt(t.Item1, t.Item2);
    }
    static void PrintStringAndInt(string s, int i) {
        Console.WriteLine("{0} {1}", s, i);
    }
}

Usando la parola chiave var da C # 3.0, possiamo rimuovere la firma del tipo dalla variabile tupla, che consente un codice un po 'più leggibile.

var t = new Tuple<string, int>("Hello", 4);

Abbiamo anche aggiunto alcuni metodi di fabbrica a una classe Tuple statica che semplifica la creazione di tuple in un linguaggio che supporta l'inferenza di tipo, come C #.

var t = Tuple.Create("Hello", 4);

Altri suggerimenti

#region tuples

    public class Tuple<T>
    {
        public Tuple(T first)
        {
            First = first;
        }

        public T First { get; set; }
    }

    public class Tuple<T, T2> : Tuple<T>
    {
        public Tuple(T first, T2 second)
            : base(first)
        {
            Second = second;
        }

        public T2 Second { get; set; }
    }

    public class Tuple<T, T2, T3> : Tuple<T, T2>
    {
        public Tuple(T first, T2 second, T3 third)
            : base(first, second)
        {
            Third = third;
        }

        public T3 Third { get; set; }
    }

    public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
    {
        public Tuple(T first, T2 second, T3 third, T4 fourth)
            : base(first, second, third)
        {
            Fourth = fourth;
        }

        public T4 Fourth { get; set; }
    }

    #endregion

E per rendere le dichiarazioni più belle:

public static class Tuple
{
    //Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
    public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
    {
        return new Tuple<T1, T2>(t1, t2);
    }
    //etc...
}

Esiste un'implementazione corretta (non rapida) C # Tuple in Librerie condivise Lokad (Open-source, ovviamente) che include le seguenti funzionalità richieste:

  • 2-5 implementazioni di tuple immutabili
  • Corretto DebuggerDisplayAttribute
  • Corretti controlli di hashing e uguaglianza
  • Assistenti per la generazione di tuple dai parametri forniti (i generici sono dedotti dal compilatore) ed estensioni per operazioni basate sulla raccolta.
  • testato in produzione.

L'implementazione di classi Tuple o il riutilizzo di classi F # in C # è solo metà della storia: ti danno la possibilità di creare tuple con relativa facilità, ma non proprio lo zucchero sintattico che le rende così belle da usare in linguaggi come F #.

Ad esempio in F # è possibile utilizzare la corrispondenza del modello per estrarre entrambe le parti di una tupla all'interno di una dichiarazione let, ad esempio

let (a, b) = someTupleFunc

Sfortunatamente fare lo stesso usando le classi F # di C # sarebbe molto meno elegante:

Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();

Le tuple rappresentano un potente metodo per restituire più valori da una chiamata di funzione senza la necessità di sporcare il codice con classi usa e getta o ricorrere a parametri di ref o out brutti. Tuttavia, a mio avviso, senza un po 'di zucchero sintattico per rendere più eleganti la loro creazione e l'accesso, sono di scarsa utilità.

A mio avviso, la funzionalità dei tipi anonimi non è una tupla, ma un costrutto molto simile. L'output di alcune query LINQ sono raccolte di tipi anonimi, che si comportano come tuple.

Ecco un'affermazione che crea una tupla digitata :-) al volo:

var p1 = new {a = "A", b = 3};

vedi: http://www.developer.com/net/csharp/ article.php / 3589916

C # 7 supporta le tuple in modo nativo:

var unnamedTuple = ("Peter", 29);
var namedTuple = (Name: "Peter", Age: 29);
(string Name, double Age) typedTuple = ("Peter", 29);

Il mio .NET open source Libreria Sasa ha avuto tuple per anni (insieme a molte altre funzionalità , come l'analisi MIME completa). Lo sto usando nel codice di produzione da alcuni anni ormai.

C # supporta tuple semplici tramite generici abbastanza facilmente (come da una risposta precedente), e con " mumble digitando " (uno dei molti possibili miglioramenti del linguaggio C #) per migliorare l'inferenza di tipo potrebbero essere molto, molto potenti.

Per quello che vale, F # supporta le tuple in modo nativo e, avendo giocato con esso, non sono sicuro che le tuple (anonime) aggiungano molto ... ciò che guadagni in brevità perdi molto rapidamente nella chiarezza del codice.

Per il codice all'interno di un singolo metodo, esistono tipi anonimi; per il codice che va al di fuori di un metodo, penso che mi atterrò a tipi di nome semplici. Certo, se un futuro C # renderà più facile renderli immutabili (anche se ancora facili da lavorare), sarò felice.

Ecco la mia serie di tuple, sono generati automaticamente da uno script Python, quindi forse sono andato un po 'fuori bordo:

Link al repository Subversion

Avrai bisogno di un nome utente / password, sono entrambi guide

Sono basati sull'ereditarietà, ma Tuple<Int32,String> non compareranno uguali a Tuple<Int32,String,Boolean> anche se hanno gli stessi valori per i due primi membri.

Implementano anche GetHashCode e ToString e così via, e molti piccoli metodi di supporto.

Esempio di utilizzo:

Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a");
Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true);
if (t1.Equals(t2))
    Console.Out.WriteLine(t1 + " == " + t2);
else
    Console.Out.WriteLine(t1 + " != " + t2);

Produrrà:

10, a != 10, a, True

Se ricordo che le mie lezioni di Informatica correttamente, le tuple sono solo dati.

Se vuoi dati raggruppati, crea classi che contengono proprietà. Se hai bisogno di qualcosa come KeyValuePair , eccolo qui.

Sarei sorpreso: C # è un linguaggio fortemente tipizzato, mentre le tuple sono adatte a linguaggi più tipicamente dinamici. C # è andato alla deriva più dinamico col passare del tempo, ma questo è zucchero sintattico, non un vero cambiamento nei tipi di dati sottostanti.

Se si desidera due valori in un'istanza, un KeyValuePair < > è un sostituto decente, anche se goffo. Puoi anche creare una struttura o una classe che farà la stessa cosa ed è espandibile.

Per renderli utili in un hashtable o in un dizionario, è probabile che si desideri fornire sovraccarichi per GetHashCode e Equals.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top