Pregunta

.Net 3.5 no admite tuplas. Lástima, pero ¿no estás seguro de si la futura versión de .net admitirá tuplas o no?

¿Fue útil?

Solución

Acabo de leer este artículo de MSDN Magazine: Building Tuple

Aquí hay extractos:

  

La próxima versión 4.0 de Microsoft   .NET Framework presenta un nuevo tipo   llamado System.Tuple. System.Tuple es un   colección de tamaño fijo de   datos de tipo heterogéneo   & nbsp;   & nbsp;

& nbsp;

  

Como una matriz, una tupla tiene un valor fijo   tamaño que no se puede cambiar una vez que tiene   ha sido creado A diferencia de una matriz, cada   elemento en una tupla puede ser diferente   tipo, y una tupla puede garantizar   escritura fuerte para cada elemento.

& nbsp;

  

Ya hay un ejemplo de un   tupla flotando alrededor de Microsoft   .NET Framework, en el   System.Collections.Generic namespace:   KeyValuePair. Si bien KeyValuePair puede considerarse como el mismo   como Tuple, ya que ambos son   tipos que contienen dos cosas,   KeyValuePair se siente diferente de   Tupla porque evoca una relación   entre los dos valores que almacena (y   con buena razón, ya que apoya el   Clase de diccionario).

     

Además, las tuplas pueden ser arbitrariamente   tamaño, mientras que KeyValuePair solo tiene   dos cosas: una clave y un valor.


Si bien algunos idiomas como F # tienen una sintaxis especial para las tuplas, puede usar el nuevo tipo de tupla común desde cualquier idioma. Revisando el primer ejemplo, podemos ver que, si bien son útiles, las tuplas pueden ser demasiado detalladas en idiomas sin sintaxis para 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 palabra clave var de C # 3.0, podemos eliminar la firma de tipo en la variable tupla, lo que permite un código algo más legible.

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

También hemos agregado algunos métodos de fábrica a una clase Tuple estática que facilita la creación de tuplas en un lenguaje que admite inferencia de tipos, como C #.

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

Otros consejos

#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

Y para hacer declaraciones más bonitas:

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

Hay una implementación adecuada (no rápida) de C # Tuple en Bibliotecas compartidas de Lokad (código abierto, por supuesto) que incluye las siguientes características requeridas:

  • 2-5 implementaciones de tuplas inmutables
  • DebuggerDisplayAttribute adecuado
  • Comprobaciones adecuadas de hashing e igualdad
  • Ayudantes para generar tuplas a partir de los parámetros proporcionados (los genéricos son inferidos por el compilador) y extensiones para operaciones basadas en colecciones.
  • probado en producción.

La implementación de clases de tupla o la reutilización de clases de F # dentro de C # es solo la mitad de la historia: estas te dan la capacidad de crear tuplas con relativa facilidad, pero no realmente el azúcar sintáctico que las hace tan agradables de usar en lenguajes como F #.

Por ejemplo, en F # puede usar la coincidencia de patrones para extraer ambas partes de una tupla dentro de una declaración let, por ejemplo,

let (a, b) = someTupleFunc

Desafortunadamente, hacer lo mismo usando las clases F # de C # sería mucho menos elegante:

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

Las tuplas representan un método poderoso para devolver múltiples valores de una llamada de función sin la necesidad de ensuciar su código con clases descartables, o recurrir a parámetros de ref o out feos. Sin embargo, en mi opinión, sin un poco de azúcar sintáctica para hacer que su creación y acceso sean más elegantes, son de uso limitado.

En mi opinión, la función de tipos anónimos no es una tupla, sino una construcción muy similar. El resultado de algunas consultas LINQ son colecciones de tipos anónimos, que se comportan como tuplas.

Aquí hay una declaración, que crea una tupla escrita a máquina :-) sobre la marcha:

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

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

C # 7 admite tuplas de forma nativa:

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

Mi código abierto .NET biblioteca Sasa ha tenido tuplas durante años (junto con muchas otras funciones) , como el análisis completo de MIME). Lo he estado usando en el código de producción durante algunos años.

C # admite tuplas simples a través de genéricos con bastante facilidad (según una respuesta anterior), y con " murmullo escribiendo " (una de las muchas posibles mejoras del lenguaje C #) para mejorar la inferencia de tipos, podrían ser muy, muy potentes.

Por lo que vale, F # admite tuplas de forma nativa, y después de haber jugado con ellas, no estoy seguro de que las tuplas (anónimas) agreguen mucho ... lo que ganas en brevedad lo pierdes muy rápidamente en claridad de código.

Para el código dentro de un único método, hay tipos anónimos; para el código que sale de un método, creo que me limitaré a los tipos con nombre simples. Por supuesto, si un futuro C # hace que sea más fácil hacerlos inmutables (aunque aún sea fácil de trabajar), estaré feliz.

Aquí está mi conjunto de tuplas, son autogeneradas por un script de Python, así que quizás me he pasado un poco por la borda:

Enlace al repositorio de Subversion

Necesitarás un nombre de usuario / contraseña, ambos son guest<

Se basan en la herencia, pero Tuple<Int32,String> no se comparará igual a Tuple<Int32,String,Boolean> incluso si tienen los mismos valores para los dos primeros miembros.

También implementan GetHashCode y ToString, etc., y muchos métodos auxiliares más pequeños.

Ejemplo de uso:

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

Saldrá:

10, a != 10, a, True

Si recuerdo mis clases de informática correctamente, las tuplas son solo datos.

Si desea datos agrupados, cree clases que contengan propiedades. Si necesita algo como el KeyValuePair , ahí está.

Me sorprendería: C # es un lenguaje fuertemente tipado, mientras que las tuplas son adecuadas para lenguajes tipados más dinámicamente. C # ha ido cambiando más dinámico a medida que pasa el tiempo, pero eso es azúcar sintáctica, no un cambio real en los tipos de datos subyacentes.

Si desea dos valores en una instancia, un KeyValuePair < > Es un sustituto decente, aunque torpe. También puede hacer una estructura o una clase que haga lo mismo y sea expandible.

Para que sean útiles en una tabla hash o diccionario, es probable que desee proporcionar sobrecargas para GetHashCode e Equals.

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