¿Cuál es la mejor manera de utilizar un par (triple, etc.) de valores como un valor en C#?

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

Pregunta

Es decir, me gustaría tener una tupla de valores.

El caso de uso en mi mente:

Dictionary<Pair<string, int>, object>

o

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

¿Hay tipos integrados como Par o Triple?¿O cuál es la mejor manera de implementarlo?

Actualizar Hay algunas implementaciones de tuplas de propósito general descritas en las respuestas, pero para las tuplas utilizadas como claves en los diccionarios, también debe verificar el cálculo correcto del código hash.Algo más de información sobre eso en otro. pregunta.

Actualización 2 Supongo que también vale la pena recordar que cuando usas algún valor como clave en el diccionario, debe ser inmutable.

¿Fue útil?

Solución

Implementé una biblioteca de tuplas en C#.Visita http://www.adventuresinsoftware.com/generics/ y haga clic en el enlace "tuplas".

Otros consejos

Clases integradas

En ciertos casos específicos, el marco .net ya proporciona clases tipo tupla que usted puede aprovechar.

Parejas y triples

el genericoSystem.Collections.Generic.KeyValuePairLa clase podría usarse como una implementación de par ad hoc.Esta es la clase que el diccionario genérico usa internamente.

Alternativamente, es posible que pueda conformarse con elSystem.Collections.DictionaryEntryEstructura que actúa como un par rudimentario y tiene la ventaja de estar disponible en Mscorlib.Sin embargo, en el lado negativo es que esta estructura no está firmemente escrita.

Parejas y Triples también están disponibles en forma deSistema.Web.UI.Par ySistema.Web.UI.Triplete clases.Aunque estas clases viven en el Sistema.Web Asamblea podrían ser perfectamente adecuados para el desarrollo de Winforms.Sin embargo, estas clases tampoco se escriben fuertemente y pueden no ser adecuadas en algunos escenarios, como un marco o biblioteca con propuestos generales.

Tuplas de orden superior

Para las tuplas de orden superior, antes de rodar su propia clase, puede que no haya una solución simple.

Si ha instalado ellenguaje F#, podrías hacer referencia al FSharp.Core.dll que contiene un conjunto de inmutables genéricosMicrosoft.Fsharp.Core.Tupla clases hasta sextuplas genéricas.Sin embargo, aunque no modificado FSharp.Code.dllSe puede redistribuir, F# es un lenguaje de investigación y un trabajo en progreso, por lo que es probable que esta solución sea de interés solo en los círculos académicos.

Si no desea crear su propia clase y se siente incómodo haciendo referencia a la biblioteca F#, un truco ingenioso podría consistir en extender la clase genérica KeyValuePair para que el miembro del valor sea en sí mismo un keyvaluePair anidado.

Por ejemplo, el siguiente código ilustra cómo puede aprovechar el keyValuePair para crear un triples:

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;

Esto permite ampliar la clase a cualquier nivel arbitrario según sea necesario.

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>();

Enrolla el tuyo

En otros casos, es posible que deba recurrir a rodar su propia clase de tupla, y esto no es difícil.

Puedes crear estructuras simples como esta:

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; }
    }
}

Marcos y bibliotecas

Este problema se ha abordado antes y existen marcos de propósito general.A continuación se muestra un enlace a uno de esos marcos:

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;
}

Avance rápido hasta 2010, .NET 4.0 ahora es compatible n-tuplas de n arbitraria.Estas tuplas implementan igualdad estructural y comparación como se esperaba.

Pair y Triplet son clases existentes en .net, consulte msdn:

Trillizo

Par

Recientemente me encontré con ellos mientras jugaba con la decodificación del estado de visualización.

Por lo general, simplemente creo mi propia estructura, que contiene los valores.A menudo es un poco más legible;)

par clavevalor es la mejor clase para ampliar si no desea crear sus propias clases.

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;

Puedes extenderlo a tantos niveles como quieras.

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

Nota:Las clases Trillizo y Par existe dentro del Sistema.Web-dll, por lo que no es muy adecuado para otras soluciones además de ASP.NET.

Puedes crear con relativa facilidad tus propias clases de tupla, lo único que potencialmente se complica es tu igualdad y las anulaciones de código hash (esencial si vas a usarlas en diccionarios).

Cabe señalar que el propio .Net KeyValuePair<TKey,TValue> estructura tiene métodos de igualdad y código hash relativamente lentos.

Suponiendo que eso no sea una preocupación para usted, todavía existe el problema de que el código termina siendo difícil de entender:

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?

En la mayoría de estos casos, me resulta más fácil crear una clase de registro específica (al menos hasta que C#4 haga que este compilador sea mágico)

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

var retVal = GetSomething();

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

Aún no se ha mencionado una solución sencilla.También puedes usar simplemente un List<T>.Está integrado, es eficiente y fácil de usar.Por supuesto, parece un poco extraño al principio, pero hace su trabajo perfectamente, especialmente para una mayor cantidad de elementos.

NGenerics: la popular biblioteca de estructuras de datos y algoritmos .Net, ha sido introducida recientemente inmutable estructuras de datos al conjunto.

Los primeros inmutables en implementar fueron par y tupla clases.El código está bien cubierto de pruebas y es bastante elegante.Usted puede comprobarlo aquí.Actualmente están trabajando en otras alternativas inmutables y deberían estar listas en breve.

No hay funciones integradas, pero crear una clase Pair<T,R> es trivial.

Sí, están System.Web.UI.Pair y System.Web.UI.Triplet (¡que tiene un creador sobrecargado para el comportamiento de tipo par!)

Para el primer caso, suelo utilizar

Dictionary<KeyValuePair<string, int>, object>

No hay clases integradas para eso.Puedes usar par clavevalor o implementar su propia implementación.

Podrías usar System.Collections.Generic.KeyValuePair como tu implementación de Pair.

O simplemente podrías implementar el tuyo propio, no son difíciles:

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

Por supuesto, algún día puede encontrarse con el problema de que Triple(string, int, int) no es compatible con Triple(int, int, string).Quizás opte por System.Xml.Linq.XElement en su lugar.

También existen los tipos Tuple<> en F#;sólo necesita hacer referencia a FSharp.Core.dll.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top