¿Una versión futura de .NET admitirá tuplas en C #?
-
02-07-2019 - |
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?
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.