Qual è il modo migliore di utilizzare una coppia (triple, ecc) di valori come un valore in C#?

StackOverflow https://stackoverflow.com/questions/101825

Domanda

Che è, mi piacerebbe avere una tupla di valori.

Il caso d'uso sulla mia mente:

Dictionary<Pair<string, int>, object>

o

Dictionary<Triple<string, int, int>, object>

Ci sono built-in tipi come Coppia o Tripla?O qual è il modo migliore di metterlo in atto?

Aggiornamento Ci sono alcuni general-purpose tuple implementazioni descritto nelle risposte, ma per tuple utilizzati come chiavi nei dizionari si deve inoltre verificare la correttezza del calcolo del codice hash.Qualche info in più su che in un altro domanda.

Aggiorna 2 Credo che sia anche la pena di ricordare che quando si utilizza un qualche valore, come una chiave nel dizionario, dovrebbe essere immutabile.

È stato utile?

Soluzione

Ho implementato una libreria di tuple in C #. Visita http://www.adventuresinsoftware.com/generics/ e fai clic sul & Quot; tuple quot &; collegamento.

Altri suggerimenti

Classi integrate

In alcuni casi specifici, il framework .net fornisce già classi simili a tuple che potresti essere in grado di sfruttare.

Coppie e triple

Il generico System.Collections.Generic.KeyValuePair La classe potrebbe essere utilizzata come implementazione di una coppia ad hoc. Questa è la classe che il Il dizionario generico utilizza internamente.

In alternativa, potresti accontentarti di System.Collections.DictionaryEntry struttura che funge da coppia rudimentale e ha il vantaggio di essendo disponibile in mscorlib. Il lato negativo, tuttavia, è che questa struttura non lo è fortemente tipizzato.

Le coppie e le triple sono disponibili anche sotto forma di System.Web.UI.Pair e System.Web.UI.Triplet classi. Anche se queste classi vivono nell'assemblea System.Web potrebbero essere perfettamente adatti allo sviluppo di winform. Tuttavia, queste classi lo sono non è fortemente tipizzato e potrebbe non essere adatto in alcuni scenari, come un framework o una libreria proposti in generale.

Tuple di ordine superiore

Per le tuple di ordine superiore, a parte il rotolamento della propria classe, potrebbe esserci non essere una soluzione semplice.

Se è stato installato il file linguaggio F # , puoi fare riferimento al FSharp.Core.dll che contiene un set di immutabili generici Microsoft.Fsharp.Core.Tuple classi fino a sestuple generici. Tuttavia, anche se un FSharp.Code.dll non modificato può essere ridistribuito, F # è un linguaggio di ricerca e un work in progress così questa soluzione potrebbe interessare solo nei circoli accademici.

Se non vuoi creare la tua classe e sei a disagio facendo riferimento alla libreria F #, un trucco intelligente potrebbe consistere nell'estensione della classe KeyValuePair generica in modo che il membro Value sia esso stesso un KeyValuePair nidificato.

Ad esempio, il codice seguente mostra come è possibile sfruttare KeyValuePair per creare una tripla:

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

Ciò consente di estendere la classe a qualsiasi livello arbitrario, come richiesto.

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string> quadruple =
    new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>();
KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string> quintuple =
    new KeyValuePair<KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string>, string>, string>();

Crea il tuo

In altri casi, potrebbe essere necessario ricorrere al proprio classe tupla, e questo non è difficile.

Puoi creare strutture semplici in questo modo:

struct Pair<T, R>
{
    private T first_;
    private R second_;

    public T First
    {
        get { return first_; }
        set { first_ = value; }
    }

    public R Second
    {
        get { return second_; }
        set { second_ = value; }
    }
}

Quadri e librerie

Questo problema è stato affrontato in precedenza e quadri per scopi generali esistono. Di seguito è riportato un collegamento a uno di questi framework:

public struct Pair<T1, T2>
{
    public T1 First;
    public T2 Second;
}

public struct Triple<T1, T2, T3>
{
    public T1 First;
    public T2 Second;
    public T3 Third;
}

Avanzamento rapido al 2010, .NET 4.0 ora supporta n-tuple di arbitrari n . Queste tuple implementano l'uguaglianza strutturale e il confronto come previsto.

Pair e Triplet sono classi esistenti in .net vedi msdn:

Triplet

Pair

Di recente mi sono imbattuto in loro, mentre giocavo con la decodifica viewstate

Di solito creo solo la mia struttura, contenente i valori. Spesso è un po 'più leggibile;)

KeyValuePair è la classe migliore da estendere se non vuoi creare le tue classi.

int id = 33;
string description = "This is a custom solution";
DateTime created = DateTime.Now;

KeyValuePair<int, KeyValuePair<string, DateTime>> triple =
   new KeyValuePair<int, KeyValuePair<string, DateTime>>();
triple.Key = id;
triple.Value.Key = description;
triple.Value.Value = created;

Puoi estenderlo a tutti i livelli che desideri.

KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string> quadruple =
   new KeyValuePair<KeyValuePair<KeyValuePair<string, string>, string, string>();

Nota : le classi Triplet e Accoppia esistono all'interno della System.Web , quindi non è molto adatto per soluzioni diverse da ASP.NET.

Si può abbastanza facilmente creare il proprio tupla classi, l'unica cosa che potenzialmente ottiene disordinato è la tua uguaglianza e hashcode sostituzioni (fondamentale se avete intenzione di usarli nei dizionari).

Va notato che .Netto propria KeyValuePair<TKey,TValue> struct ha relativamente lenta uguaglianza e metodi hashcode.

Supponendo che non è una preoccupazione per voi c'è ancora il problema che il codice finisce per essere difficile da capire:

public Tuple<int, string, int> GetSomething() 
{
    //do stuff to get your multi-value return
}

//then call it:
var retVal = GetSomething();

//problem is what does this mean?
retVal.Item1 / retVal.Item3; 
//what are item 1 and 3?

Nella maggior parte di questi casi è più facile creare un record specifico di classe (almeno fino a C#4 fa questo compilatore-magia)

class CustomRetVal {
    int CurrentIndex { get; set; }
    string Message { get; set; }
    int CurrentTotal { get; set; }
}

var retVal = GetSomething();

//get % progress
retVal.CurrentIndex / retVal.CurrentTotal;

Non è stata ancora menzionata una soluzione semplice. Puoi anche usare solo List<T>. È integrato, efficiente e facile da usare. Certo, all'inizio sembra un po 'strano, ma fa perfettamente il suo lavoro, specialmente per un maggior numero di elementi.

NGenerics - la popolare libreria di algoritmi .Net e strutture di dati, ha recentemente introdotto immutabili strutture di dati nel set.

I primi immutabili da implementare erano le classi coppia e tupla . Il codice è ben coperto di test ed è abbastanza elegante. Puoi controllarlo qui . Stanno lavorando su altre alternative immutabili al momento e dovrebbero essere pronti a breve.

Non ci sono ins incorporati, ma una coppia < T, R > la classe è banale da creare.

Sì, c'è System.Web.UI.Pair e System.Web.UI.Triplet (che ha un creatore sovraccarico per il comportamento di tipo Pair!)

Per il primo caso, di solito uso

Dictionary<KeyValuePair<string, int>, object>

Non ci sono classi integrate per questo. Puoi utilizzare KeyValuePair o implementare la tua implementazione.

È possibile utilizzare System.Collections.Generic.KeyValuePair come implementazione di Pair.

O potresti semplicemente implementare i tuoi, non sono difficili:

public class Triple<T, U, V>
{
  public T First {get;set;}
  public U Second {get;set;}
  public V Third {get;set;}
}

Naturalmente, un giorno potresti riscontrare un problema per cui Triple (string, int, int) non è compatibile con Triple (int, int, string). Forse andare con System.Xml.Linq.XElement invece.

Esistono anche le Tuple < > digita in F #; devi solo fare riferimento a FSharp.Core.dll.

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