c# - example - ¿Cómo inicializar fácilmente una lista de tuplas?
tuple c# ejemplo (8)
¡Sí! Esto es posible
La sintaxis {} del inicializador de la colección funciona en cualquier tipo de IEnumerable que tenga un método Add con la cantidad correcta de argumentos. Sin molestarse en cómo funciona eso bajo las coberturas, eso significa que simplemente puede extender desde la Lista <T> , agregar un método personalizado Agregar para inicializar su T , ¡y listo!
public class TupleList<T1, T2> : List<Tuple<T1, T2>>
{
public void Add( T1 item, T2 item2 )
{
Add( new Tuple<T1, T2>( item, item2 ) );
}
}
Esto le permite hacer lo siguiente:
var groceryList = new TupleList<int, string>
{
{ 1, "kiwi" },
{ 5, "apples" },
{ 3, "potatoes" },
{ 1, "tomato" }
};
Me encantan las tuples . Le permiten agrupar rápidamente información relevante sin tener que escribir una estructura o clase para ella. Esto es muy útil al refactorizar código muy localizado.
Inicializar una lista de ellos, sin embargo, parece un poco redundante.
var tupleList = new List<Tuple<int, string>>
{
Tuple.Create( 1, "cow" ),
Tuple.Create( 5, "chickens" ),
Tuple.Create( 1, "airplane" )
};
¿No hay una mejor manera? Me encantaría una solución a lo largo de las líneas del inicializador del Diccionario .
Dictionary<int, string> students = new Dictionary<int, string>()
{
{ 111, "bleh" },
{ 112, "bloeh" },
{ 113, "blah" }
};
¿No podemos usar una sintaxis similar?
¿Por qué les gustan las tuplas? Es como tipos anónimos: no hay nombres. No se puede entender la estructura de los datos.
Me gustan las clases clasicas
class FoodItem
{
public int Position { get; set; }
public string Name { get; set; }
}
List<FoodItem> list = new List<FoodItem>
{
new FoodItem { Position = 1, Name = "apple" },
new FoodItem { Position = 2, Name = "kiwi" }
};
C # 6 agrega una nueva característica solo para esto: métodos para agregar extensiones. 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. Cuando extienda cualquier tipo enumerable con un método Add()
, podrá usarlo en expresiones de inicialización de colección. Así que ya no tiene que derivar de las listas explícitamente ( share ), simplemente puede extenderlo.
public static class TupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
T1 item1, T2 item2)
{
list.Add(Tuple.Create(item1, item2));
}
public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> 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<Tuple<int, string>>
{
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
{ 4, "four" },
{ 5, "five" },
};
var points = new ObservableCollection<Tuple<double, double, double>>
{
{ 0, 0, 0 },
{ 1, 2, 3 },
{ -4, -2, 42 },
};
Por supuesto, no está restringido a la extensión de colecciones de tuplas, puede ser para colecciones de cualquier tipo específico para el que desee la sintaxis especial.
public static class BigIntegerListExtensions
{
public static void Add(this IList<BigInteger> list,
params byte[] value)
{
list.Add(new BigInteger(value));
}
public static void Add(this IList<BigInteger> list,
string value)
{
list.Add(BigInteger.Parse(value));
}
}
var bigNumbers = new List<BigInteger>
{
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 para que usted también tenga la opción de usarlas. Desafortunadamente, no hay conversiones implícitas definidas entre los dos.
public static class ValueTupleListExtensions
{
public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
ValueTuple<T1, T2> item) => list.Add(item.ToTuple());
}
De esta manera, la inicialización de la lista se verá aún mejor.
var points = new List<Tuple<int, int, int>>
{
(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),
};
Creo que una técnica es un poco más fácil y que no se ha mencionado anteriormente aquí:
var asdf = new [] {
(Age: 1, Name: "cow"),
(Age: 2, Name: "bird")
}.ToList();
Creo que eso es un poco más limpio que:
var asdf = new List<Tuple<int, string>> {
(Age: 1, Name: "cow"),
(Age: 2, Name: "bird")
};
Pregunta antigua, pero esto es lo que normalmente hago para hacer las cosas un poco más legibles:
Func<int, string, Tuple<int, string>> tc = Tuple.Create;
var tupleList = new List<Tuple<int, string>>
{
tc( 1, "cow" ),
tc( 5, "chickens" ),
tc( 1, "airplane" )
};
Puedes hacerlo llamando al constructor cada vez que sea un poco mejor
var tupleList = new List<Tuple<int, string>>
{
new Tuple<int, string>(1, "cow" ),
new Tuple<int, string>( 5, "chickens" ),
new Tuple<int, string>( 1, "airplane" )
};
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 hacerlo:
var tupleList = new(int, string)[]
{
(1, "cow"),
(5, "chickens"),
(1, "airplane")
};
Y si no te gusta "Item1" y "Item2", 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")
};
que te permite hacer: tupleList[0].Index
y tupleList[0].Name
Marco 4.6.2 y por debajo
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 vacas, pollos o aviones. Yo estaría muy desgarrado.
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<Color, string>