c# - tipos - Una lista genérica de clase anónima
qué son generics (19)
Aquí está la respuesta.
string result = String.Empty;
var list = new[]
{
new { Number = 10, Name = "Smith" },
new { Number = 10, Name = "John" }
}.ToList();
foreach (var item in list)
{
result += String.Format("Name={0}, Number={1}/n", item.Name, item.Number);
}
MessageBox.Show(result);
En C # 3.0 puedes crear una clase anónima con la siguiente sintaxis
var o = new { Id = 1, Name = "Foo" };
¿Hay alguna manera de agregar estas clases anónimas a una lista genérica?
Ejemplo:
var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };
List<var> list = new List<var>();
list.Add(o);
list.Add(o1);
Otro ejemplo:
List<var> list = new List<var>();
while (....)
{
....
list.Add(new {Id = x, Name = y});
....
}
Aquí está mi intento.
List<object> list = new List<object> { new { Id = 10, Name = "Testing1" }, new {Id =2, Name ="Testing2" }};
Se me ocurrió esto cuando escribí algo similar para hacer una lista anónima para un tipo personalizado.
Aquí hay otro método para crear una Lista de tipos anónimos que le permite comenzar con una lista vacía, pero aún así tener acceso a IntelliSense.
var items = "".Select( t => new {Id = 1, Name = "foo"} ).ToList();
Si desea conservar el primer elemento, solo coloque una letra en la cadena.
var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();
En la última versión 4.0, se puede usar la dinámica como a continuación.
var list = new List<dynamic>();
list.Add(new {
Name = "Damith"
});
foreach(var item in list){
Console.WriteLine(item.Name);
}
}
En lugar de esto:
var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };
List <var> list = new List<var>();
list.Add(o);
list.Add(o1);
Podrías hacer esto:
var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };
List<object> list = new List<object>();
list.Add(o);
list.Add(o1);
Sin embargo, obtendrá un error de tiempo de compilación si intenta hacer algo como esto en otro ámbito, aunque funciona en tiempo de ejecución:
private List<object> GetList()
{
List<object> list = new List<object>();
var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };
list.Add(o);
list.Add(o1);
return list;
}
private void WriteList()
{
foreach (var item in GetList())
{
Console.WriteLine("Name={0}{1}", item.Name, Environment.NewLine);
}
}
El problema es que solo los miembros de Object están disponibles en tiempo de ejecución, aunque intellisense mostrará el id y el nombre de las propiedades.
En .net 4.0, una solución es usar la palabra clave istead dinámico del objeto en el código anterior.
Otra solución es utilizar la reflexión para obtener las propiedades.
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var anonymous = p.GetList(new[]{
new { Id = 1, Name = "Foo" },
new { Id = 2, Name = "Bar" }
});
p.WriteList(anonymous);
}
private List<T> GetList<T>(params T[] elements)
{
var a = TypeGenerator(elements);
return a;
}
public static List<T> TypeGenerator<T>(T[] at)
{
return new List<T>(at);
}
private void WriteList<T>(List<T> elements)
{
PropertyInfo[] pi = typeof(T).GetProperties();
foreach (var el in elements)
{
foreach (var p in pi)
{
Console.WriteLine("{0}", p.GetValue(el, null));
}
}
Console.ReadLine();
}
}
}
Esta es una pregunta antigua, pero pensé que pondría en mi respuesta C # 6. A menudo tengo que configurar datos de prueba que se ingresan fácilmente en el código como una lista de tuplas. Con un par de funciones de extensión, es posible tener este formato agradable y compacto, sin repetir los nombres en cada entrada.
var people= new List<Tuple<int, int, string>>() {
{1, 11, "Adam"},
{2, 22, "Bill"},
{3, 33, "Carol"}
}.Select(t => new { Id = t.Item1, Age = t.Item2, Name = t.Item3 });
Esto le da un IEnumerable: si desea una lista que puede agregar, simplemente agregue ToList ().
La magia proviene de la extensión personalizada Agregue métodos para tuplas, como se describe en https://.com/a/27455822/4536527 .
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...
}
Lo único que no me gusta es que los tipos estén separados de los nombres, pero si realmente no quieres crear una nueva clase, este enfoque aún te permitirá tener datos legibles.
Hay muchas maneras de hacer esto, pero algunas de las respuestas aquí están creando una lista que contiene elementos de basura, lo que requiere que borre la lista.
Si está buscando una lista vacía del tipo genérico, use una Selección contra una lista de tuplas para hacer la lista vacía. Ningún elemento será instanciado.
Aquí está el one-liner para crear una lista vacía:
var emptyList = new List<Tuple<int, string>>()
.Select(t => new { Id = t.Item1, Name = t.Item2 }).ToList();
Luego puedes agregarlo usando tu tipo genérico:
emptyList.Add(new { Id = 1, Name = "foo" });
emptyList.Add(new { Id = 2, Name = "bar" });
Como alternativa, puedes hacer algo como a continuación para crear la lista vacía (pero, prefiero el primer ejemplo porque también puedes usarlo para una colección poblada de tuplas):
var emptyList = new List<object>()
.Select(t => new { Id = default(int), Name = default(string) }).ToList();
Intenta con esto:
var result = new List<object>();
foreach (var test in model.ToList()) {
result.Add(new {Id = test.IdSoc,Nom = test.Nom});
}
No exactamente, pero puedes decir List<object>
y las cosas funcionarán. Sin embargo, la list[0].Id
no funcionará.
Esto funcionará en el tiempo de ejecución en C # 4.0 al tener una List<dynamic>
, es decir, no obtendrá IntelliSense.
Para su segundo ejemplo, donde tiene que inicializar una nueva List<T>
, una idea es crear una lista anónima y luego borrarla.
var list = new[] { o, o1 }.ToList();
list.Clear();
//and you can keep adding.
while (....)
{
....
list.Add(new { Id = x, Name = y });
....
}
O como método de extensión, debería ser más fácil:
public static List<T> GetEmptyListOfThisType<T>(this T item)
{
return new List<T>();
}
//so you can call:
var list = new { Id = 0, Name = "" }.GetEmptyListOfThisType();
O probablemente incluso más corto,
var list = new int[0].Select(x => new { Id = 0, Name = "" }).Tolist();
Podrías hacerlo:
var list = new[] { o, o1 }.ToList();
Hay muchas maneras de desollar a este gato, pero básicamente todos usarán la inferencia de tipos en alguna parte, lo que significa que tienes que llamar a un método genérico (posiblemente como un método de extensión). Otro ejemplo podría ser:
public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}
var list = CreateList(o, o1);
Tienes la idea :)
Puedes crear una lista de dinámica.
List<dynamic> anons=new List<dynamic>();
foreach (Model model in models)
{
var anon= new
{
Id = model.Id,
Name=model.Name
};
anons.Add(anon);
}
"dinámico" se inicializa con el primer valor agregado.
Puedes hacer esto en tu código.
var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });
Puedes hacerlo de esta manera:
var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };
var array = new[] { o, o1 };
var list = array.ToList();
list.Add(new { Id = 3, Name = "Yeah" });
Me parece un poco "pirata", pero funciona, si realmente necesitas tener una lista y no puedes usar la matriz anónima.
Revisé el IL en varias respuestas. Este código proporciona de manera eficiente una lista vacía:
using System.Linq;
…
var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();
Usualmente uso lo siguiente; Principalmente porque luego "empiezas" con una lista que está vacía.
var list = Enumerable.Range(0, 0).Select(e => new { ID = 1, Name = ""}).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );
//etc.
Últimamente, lo he estado escribiendo así en su lugar:
var list = Enumerable.Repeat(new { ID = 1, Name = "" }, 0).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );
Usar el método de repetición también le permitiría hacer:
var myObj = new { ID = 1, Name = "John" };
var list = Enumerable.Repeat(myObj, 1).ToList();
list.Add(new { ID = 2, Name = "Liana" });
..que le da la lista inicial con el primer elemento ya agregado.
supongo
List<T> CreateEmptyGenericList<T>(T example) {
return new List<T>();
}
void something() {
var o = new { Id = 1, Name = "foo" };
var emptyListOfAnonymousType = CreateEmptyGenericList(o);
}
trabajará.
También podrías considerar escribirlo así:
void something() {
var String = string.Emtpy;
var Integer = int.MinValue;
var emptyListOfAnonymousType = CreateEmptyGenericList(new { Id = Integer, Name = String });
}
static void Main()
{
List<int> list = new List<int>();
list.Add(2);
list.Add(3);
list.Add(5);
list.Add(7);
}
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);