¿Cómo inicializar fácilmente una lista de tuplas?

Amo las tuplas Le permiten agrupar rápidamente información relevante sin tener que escribir una estructura o clase para ella. Esto es muy útil al refacturar código muy localizado.

Inicializar una lista de ellos sin embargo parece un poco redundante.

var tupleList = new List<Tuple> { Tuple.Create( 1, "cow" ), Tuple.Create( 5, "chickens" ), Tuple.Create( 1, "airplane" ) }; 

¿No hay una mejor manera? Me encantaría una solución similar a la del diccionario inicializador .

 Dictionary students = new Dictionary() { { 111, "bleh" }, { 112, "bloeh" }, { 113, "blah" } }; 

¿No podemos usar una syntax similar?

c # 7.0 te permite hacer esto:

  var tupleList = new List< (int, string)> { (1, "cow"), (5, "chickens"), (1, "airplane") }; 

Si no necesita una List , sino solo una matriz, puede hacer:

  var tupleList = new(int, string)[] { (1, "cow"), (5, "chickens"), (1, "airplane") }; 

Y si no te gusta “Artículo1” y “Artículo2”, puedes hacer:

  var tupleList = new List< (int Index, string Name)> { (1, "cow"), (5, "chickens"), (1, "airplane") }; 

o

  var tupleList = new (int Index, string Name)[] { (1, "cow"), (5, "chickens"), (1, "airplane") }; 

lo que te permite hacer: tupleList[0].Index y tupleList[0].Name

Marco 4.6.2 y abajo

Debe instalar System.ValueTuple desde Nuget Package Manager.

Marco 4.7 y superior

Está integrado en el marco. No instale System.ValueTuple . De hecho, elimínelo y elimínelo del directorio bin.

nota: En la vida real, no podría elegir entre vaca, gallina o avión. Estaría realmente desgarrado.

¡Sí! Esto es posible

La syntax {} del inicializador de colección funciona en cualquier tipo de IEnumerable que tenga un método Add con la cantidad correcta de argumentos. Sin molestarnos en cómo funciona eso, eso significa que simplemente puede extenderse desde la Lista , agregar un método personalizado de Agregar para inicializar su T , ¡y listo!

 public class TupleList : List> { public void Add( T1 item, T2 item2 ) { Add( new Tuple( item, item2 ) ); } } 

Esto le permite hacer lo siguiente:

 var groceryList = new TupleList { { 1, "kiwi" }, { 5, "apples" }, { 3, "potatoes" }, { 1, "tomato" } }; 

C # 6 agrega una nueva función solo para esto: extensión Agregar métodos. Esto siempre ha sido posible para VB.net, pero ahora está disponible en C #.

Ahora no tiene que agregar métodos Add() directamente a sus clases, puede implementarlos como métodos de extensión. Al extender cualquier tipo enumerable con un método Add() , podrá usarlo en expresiones de inicialización de colección. Entonces no tiene que derivar explícitamente de las listas ( como se menciona en otra respuesta ), simplemente puede extenderlo.

 public static class TupleListExtensions { public static void Add(this IList> list, T1 item1, T2 item2) { list.Add(Tuple.Create(item1, item2)); } public static void Add(this IList> list, T1 item1, T2 item2, T3 item3) { list.Add(Tuple.Create(item1, item2, item3)); } // and so on... } 

Esto le permitirá hacer esto en cualquier clase que implemente IList<> :

 var numbers = new List> { { 1, "one" }, { 2, "two" }, { 3, "three" }, { 4, "four" }, { 5, "five" }, }; var points = new ObservableCollection> { { 0, 0, 0 }, { 1, 2, 3 }, { -4, -2, 42 }, }; 

Por supuesto, no está limitado a extender colecciones de tuplas, puede ser para colecciones de cualquier tipo específico para el que desee la syntax especial.

 public static class BigIntegerListExtensions { public static void Add(this IList list, params byte[] value) { list.Add(new BigInteger(value)); } public static void Add(this IList list, string value) { list.Add(BigInteger.Parse(value)); } } var bigNumbers = new List { new BigInteger(1), // constructor BigInteger(int) 2222222222L, // implicit operator BigInteger(long) 3333333333UL, // implicit operator BigInteger(ulong) { 4, 4, 4, 4, 4, 4, 4, 4 }, // extension Add(byte[]) "55555555555555555555555555555555555555", // extension Add(string) }; 

C # 7 agregará soporte para tuplas integradas en el lenguaje, aunque serán de un tipo diferente ( System.ValueTuple en System.ValueTuple lugar). Por lo tanto, sería bueno agregar sobrecargas para las tuplas de valor, por lo que también tiene la opción de usarlas. Lamentablemente, no hay conversiones implícitas definidas entre los dos.

 public static class ValueTupleListExtensions { public static void Add(this IList> list, ValueTuple item) => list.Add(item.ToTuple()); } 

De esta forma, la inicialización de la lista se verá aún mejor.

 var points = new List> { (0, 0, 0), (1, 2, 3), (-1, 12, -73), }; 

Pero en lugar de pasar por todo este problema, podría ser mejor cambiar a usar ValueTuple exclusivamente.

 var points = new List< (int, int, int)> { (0, 0, 0), (1, 2, 3), (-1, 12, -73), }; 

Puedes hacer esto llamando al constructor cada vez que sea ligeramente mejor

 var tupleList = new List> { new Tuple(1, "cow" ), new Tuple( 5, "chickens" ), new Tuple( 1, "airplane" ) }; 

Una vieja pregunta, pero esto es lo que suelo hacer para que las cosas sean un poco más legibles:

 Func> tc = Tuple.Create; var tupleList = new List> { tc( 1, "cow" ), tc( 5, "chickens" ), tc( 1, "airplane" ) }; 

¿Por qué les gustan las tuplas? Es como tipos anónimos: sin nombres. No puedo entender la estructura de los datos.

Me gustan las clases clásicas

 class FoodItem { public int Position { get; set; } public string Name { get; set; } } List list = new List { new FoodItem { Position = 1, Name = "apple" }, new FoodItem { Position = 2, Name = "kiwi" } }; 

Una técnica que creo que es un poco más fácil y que no se ha mencionado antes aquí:

 var asdf = new [] { (Age: 1, Name: "cow"), (Age: 2, Name: "bird") }.ToList(); 

Creo que es un poco más limpio que:

 var asdf = new List> { (Age: 1, Name: "cow"), (Age: 2, Name: "bird") }; 
  var colors = new[] { new { value = Color.White, name = "White" }, new { value = Color.Silver, name = "Silver" }, new { value = Color.Gray, name = "Gray" }, new { value = Color.Black, name = "Black" }, new { value = Color.Red, name = "Red" }, new { value = Color.Maroon, name = "Maroon" }, new { value = Color.Yellow, name = "Yellow" }, new { value = Color.Olive, name = "Olive" }, new { value = Color.Lime, name = "Lime" }, new { value = Color.Green, name = "Green" }, new { value = Color.Aqua, name = "Aqua" }, new { value = Color.Teal, name = "Teal" }, new { value = Color.Blue, name = "Blue" }, new { value = Color.Navy, name = "Navy" }, new { value = Color.Pink, name = "Pink" }, new { value = Color.Fuchsia, name = "Fuchsia" }, new { value = Color.Purple, name = "Purple" } }; foreach (var color in colors) { stackLayout.Children.Add( new Label { Text = color.name, TextColor = color.value, }); FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)) } this is a Tuple