2010-02-24 12 views
60

¿Hay alguna manera de declarar un objeto de lista de tipo anónimo? Me refiero aDeclaración de tipos anónimos Lista

List<var> someVariable = new List<var>(); 
someVariable.Add(
      new{Name="Krishna", 
       Phones = new[] {"555-555-5555", "666-666-6666"}} 
       ); 

Esto se debe a que necesito crear una colección en tiempo de ejecución. Gracias de antemano

+2

No entiendo cuál es el punto de una lista con tipos anónimos. –

+3

Hay algunos casos de uso para ellos. Un ejemplo es cuando necesita mezclar una consulta LINQ-to-SQL con una colección respaldada por memoria. – Polynomial

Respuesta

53

Se trata de un poco de hackeo, pero se puede hacer.

static List<T> CreateListFromSingle<T>(T value) { 
    var list = new List<T>(); 
    list.Add(value); 
    return list; 
} 

var list = CreateListFromSingle(
    new{Name="Krishna", 
       Phones = new[] {"555-555-5555", "666-666-6666"}} 
       ); 
+22

Ack. Esto es inteligente, y funciona, pero estaría tan enojado si alguno de mis desarrolladores alguna vez lo hiciera en el trabajo real ... +1 por el buen truco, sin embargo. –

+0

@Reed, acordó que es doloroso mirar pero funciona – JaredPar

+0

sin ofender, pero espero que no use este código ...: D –

13

No se puede hacer una colección de un tipo anónimo como este.

Si necesita hacer esto, necesitará usar List<object>, o crear una clase o estructura personalizada para su tipo.


Editar:

Voy a reformular esto:

Aunque, técnicamente, es posible hacer una lista de un tipo anónimo, yo fuertemente recomendaría no hacer esto. Casi siempre hay un enfoque mejor, ya que hacer esto es simplemente crear un código que casi no se puede mantener. Recomiendo hacer un tipo personalizado para mantener sus valores en lugar de usar tipos anónimos.

un tipo personalizado tendrá todas las mismas capacidades (ya que los tipos anónimos se definen, por el compilador, en tiempo de compilación), pero será mucho más comprensible por el desarrollador que te siga ...


Y sólo para jugar, también, aquí está mi entrada para el "código que nunca había realmente quiero usar en el mundo real":

var customer = new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } }; 
var someVariable = new[]{1}.Select(i => customer).ToList(); 
+2

De acuerdo. Creo que es una buena regla es que si le preocupa el tipo de objeto tipo anónimo, entonces está haciendo (o preparándose para) hacer algo incorrecto. – kervin

+1

+1 demora medio segundo crear un tipo personalizado y ahorra horas de depuración código inmanejable/confuso. –

1

no creo que esto es posible. ¿Tal vez en C# 4 usando la palabra clave dinámica?

+0

puede, pero no sería una buena idea. Este es un buen ejemplo de por qué algunas personas creen que se abusará de la palabra clave 'dynamic'. –

47

Puede hacer una lista como esta, pero de nuevo tendrá que utilizar algunos hackers serios, y tendrá que usar algunas situaciones de "escriba por ejemplo". Por ejemplo:

// create the first list by using a specific "template" type. 
var list = new [] { new { Name="", Phones=new[] { "" } } }.ToList(); 

// clear the list. The first element was just an example. 
list.Clear(); 

// start adding "actual" values. 
list.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } }); 
+12

Bien, esto es, de nuevo, inteligente y espeluznante para ver al mismo tiempo ... +1 –

+2

inteligente, no he visto ese truco en línea antes de – JaredPar

+1

Gracias, lo guardaré para el futuro. – Krishna

25

En general se puede utilizar el (posiblemente con mal olor) proyectada por ejemplo truco que otros han mencionado para crear instancias de cualquier tipo genérico parametrizado con un tipo anónimo para el argumento de tipo. Sin embargo, para List<T> hay una manera un poco menos bruto para hacerlo:

var array = new[] { 
    new { 
    Name="Krishna", 
    Phones = new[] {"555-555-5555", "666-666-6666"} 
    } 
}; 
var list = array.ToList(); 

Su esbozo de una sintaxis propuesta es similar a una característica que no implementaron para C# 3 o 4, pero hemos considerado. Llamamos a la función de "tipos" Mumble, y sería algo parecido a esto:

List<?> myList = new List<?>() { 
    new { 
    Name="Krishna", 
    Phones = new[] {"555-555-5555", "666-666-6666"} 
    } 
}; 

nos llaman "tipos mumble" porque por supuesto que lo había leído "miLista es una nueva lista de hrmmf". :-)

La idea es que el compilador revise los inicializadores y haga todo lo posible para descubrir cuál podría ser el tipo, de la misma manera que "var" significa "ver el inicializador y descubrir cuál es el tipo de la variable ". Si usamos "var" como el "murmullo" o "?" (que es similar a lo que hace Java en una función relacionada), o algo más es una pregunta abierta.

En cualquier caso, no aguantaría la respiración esperando esta función si fuera usted. Hasta ahora no ha alcanzado el límite para varias versiones de idiomas, pero creo que permanecerá en la lista de posibilidades durante un tiempo más. Si, hipotéticamente hablando, estuviéramos diseñando versiones futuras del lenguaje. Que podríamos o no ser. Recuerde, las reflexiones de Eric sobre las versiones futuras de C# son solo para fines de entretenimiento.

+1

+1 para el buen nombre ("tipos de murmullo") y +1 por no implementarlo. Me imagino que el costo de hacer esto no es barato, y el trabajo es muy fácil, y más fácil de mantener ... – Daryl

8

Pasé mucho tiempo tratando de encontrar una manera de salvar a mí mismo algún tiempo utilizando una lista de los tipos anónimos, a continuación, se dieron cuenta de que era probablemente más rápido sólo para usar una clase privada dentro de la clase actual ...

private class Lookup { 
    public int Index; 
    public string DocType; 
    public string Text; 
} 
private void MyMethod() { 
    List<Lookup> all_lookups = new List<Lookup> { 
     new Lookup() {Index=4, DocType="SuperView", Text="SuperView XML File"}, 
     new Lookup() {Index=2, DocType="Word", Text="Microsoft Word Document"} 
    }; 
    // Use my all_lookups variable here... 

} 
8

Esto es un enfoque que es un poco más limpio que muchas de las otras sugerencias:

var list = Enumerable.Repeat(new { Name = "", Phones = new[] { "" } }, 0) 
       .ToList(); 

// ... 
list.Add(new { Name = "Krishna", 
       Phones = new[] { "555-555-5555", "666-666-6666" } }); 
+0

solución muy elegante - gracias amable señor. –

61

¿Qué tal dinámica?

List<dynamic> dynamicList = new List<dynamic>(); 


dynamicList.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } }); 
+0

Gracias @JaiKannah, definitivamente debería ser la respuesta para .NET 4.x. Nos acerca mucho más a la flexibilidad de las matrices PHP sin la piratería. – sonjz

+0

Esta es una solución mucho mejor que las otras ... – Octane

+5

'dynamic' = no intellisense. Gracias, pero no. Incluso el 'Item1' de la tupla fea es mejor. – Sinatr

Cuestiones relacionadas