¿Una versión futura de .NET admitirá tuplas en C #?

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

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 una colección de tamaño fijo de datos de tipo heterogéneo.

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

Ya hay un ejemplo de una tupla flotando alrededor de Microsoft .NET Framework, en el espacio de nombres System.Collections.Generic: KeyValuePair. Aunque se puede pensar que KeyValuePair es lo mismo que Tuple, ya que ambos tipos tienen dos cosas, KeyValuePair se siente diferente de Tuple porque evoca una relación entre los dos valores que almacena (y con buena razón, ya que admite la clase Dictionary )

Además, las tuplas pueden ser arbitrariamente dimensionadas, mientras que KeyValuePair contiene solo dos cosas: una clave y un valor.


Mientras que algunos lenguajes como F # tienen una syntax especial para tuplas, puede usar el nuevo tipo de tupla común desde cualquier idioma. Revisando el primer ejemplo, podemos ver que aunque es útil, las tuplas pueden ser demasiado detalladas en los lenguajes sin syntax para una tupla:

class Program { static void Main(string[] args) { Tuple t = new Tuple("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("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 la inferencia de tipos, como C #.

 var t = Tuple.Create("Hello", 4); 
 #region tuples public class Tuple { public Tuple(T first) { First = first; } public T First { get; set; } } public class Tuple : Tuple { public Tuple(T first, T2 second) : base(first) { Second = second; } public T2 Second { get; set; } } public class Tuple : Tuple { public Tuple(T first, T2 second, T3 third) : base(first, second) { Third = third; } public T3 Third { get; set; } } public class Tuple : Tuple { 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(1, "2") public static Tuple New(T1 t1, T2 t2) { return new Tuple(t1, t2); } //etc... } 

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

  • 2-5 implementaciones de tuplas inmutables
  • DebuggerProDisplayAttribute
  • Comprobaciones de hash e igualdad correctas
  • Ayudantes para generar tuplas a partir de los parámetros proporcionados (los generics se deducen por comstackdor) y extensiones para operaciones basadas en recostackción.
  • probado en producción.

Implementar clases Tuple o reutilizar clases F # dentro de C # es solo la mitad de la historia, estas te dan la capacidad de crear tuplas con relativa facilidad, pero no 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 statement let, por ejemplo

 let (a, b) = someTupleFunc 

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

 Tuple 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 desechables, o recurriendo a parámetros de ref o out desagradables. Sin embargo, en mi opinión, sin azúcar sintáctico para hacer que su creación y acceso sean más elegantes, tienen un uso limitado.

En mi opinión, la característica 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 statement, que crea una tupla tipeada 🙂 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 biblioteca de fuente abierta .NET Sasa ha tenido tuplas durante años (junto con muchas otras funcionalidades, como el análisis MIME completo). Lo he estado utilizando en el código de producción durante unos años.

C # soporta tuplas simples a través de generics con bastante facilidad (según una respuesta anterior), y con “tipar tipeo” (una de las muchas mejoras posibles del lenguaje C #) para mejorar la inferencia de tipo podrían ser muy, muy poderosas.

Por lo que vale, F # admite tuplas de forma nativa, y después de haber jugado con él, no estoy seguro de que las tuplas (anónimas) añadan mucho … lo que gana en brevedad se pierde muy rápidamente en la claridad del código.

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

Aquí está mi conjunto de tuplas, están autogeneradas por una secuencia de comandos de Python, por lo que tal vez haya ido un poco por la borda:

Enlace al repository de Subversion

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

Se basan en la herencia, pero Tuple no se comparará con Tuple incluso si tienen los mismos valores para los dos primeros miembros.

También implementan GetHashCode y ToString, entre otros, y muchos métodos pequeños de ayuda.

Ejemplo de uso:

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

Se producirá:

 10, a != 10, a, True 

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

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

Me sorprendería que C # sea un lenguaje fuertemente tipado, mientras que las tuplas son adecuadas para lenguajes con más tipos dynamics. C # ha ido a la deriva más dynamic a medida que pasa el tiempo, pero eso es azúcar sintáctica, no un cambio real en los tipos de datos subyacentes.

Si quiere dos valores en una instancia, un KeyValuePair <> es un sustituto decente, aunque torpe. También puede crear una estructura o una clase que haga lo mismo y que sea ampliable.

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