2011-06-06 19 views
15

¿Es posible combinar un inicializador de listas y un inicializador de objetos al mismo tiempo? Dada la siguiente definición de clase:Combinación del inicializador de listas y el inicializador de objetos

class MyList : List<int> 
{ 
    public string Text { get; set; } 
} 

// we can do this 
var obj1 = new MyList() { Text="Hello" }; 

// we can also do that 
var obj2 = new MyList() { 1, 2, 3 }; 

// but this one doesn't compile 
//var obj3 = new MyList() { Text="Hello", 1, 2, 3 }; 

Es éste por diseño o es sólo un error o característica que falta del compilador de C#?

Respuesta

25

No, mirando a las definiciones de la sección 7.6.10 de la # spec C, una expresión object-or-collection-initializer es ya sea un object-initializero un collection-initializer.

Un object-initializer está compuesto de múltiples member-initializer s, cada uno de los cuales es de la forma initializer = initializer-value mientras que un collection-initializer está compuesto de múltiples element-initializer s, cada uno de los cuales es un non-assigment-expression.

Parece que es por diseño, posiblemente por simplicidad. No puedo decir que alguna vez quería para hacer esto, para ser honesto. (Por lo general no se derivaría de List<int> para empezar - Me lo componen en su lugar.) Me gustaría realmente gustado ver:

var obj3 = new MyList { 1, 2, Text = "Hello", 3, 4 }; 

EDIT: Si muy, muy desea habilitar esto, podría poner esto en la clase:

class MyList : List<int> 
{ 
    public string Text { get; set; } 
    public MyList Values { get { return this; } } 
} 

momento en el que se podría escribir:

var obj3 = new MyList { Text = "Hello", Values = { 1, 2, 3, 4 } }; 
+0

La especificación debe obligar a la parte inicializador de objeto y la parte de lista de inicialización uno tras otro y no intercalada :) – codymanix

+0

@codymanix: Vea mi edición para una solución alternativa. –

+0

También necesitarías un juego. – Tejs

3

no, es un no es un insecto. Es por diseño del lenguaje.

Cuando se escribe

var obj1 = new MyList() { Text="Hello" }; 

esto se traduce efectivamente por el compilador para

MyList temp = new MyList(); 
temp.Text = "Hello"; 
MyList obj = temp; 

Cuando se escribe

var obj2 = new MyList() { 1, 2, 3 }; 

ello se traduce efectivamente por el compilador para

MyList temp = new MyList(); 
temp.Add(1); 
temp.Add(2); 
temp.Add(3); 
MyList obj2 = temp; 

Tenga en cuenta que en el primer caso está utilizando un inicializador de objetos, pero en el segundo caso está utilizando un inicializador de colecciones. No existe tal cosa como un inicializador de objetos y colecciones. Está inicializando las propiedades de su objeto o está inicializando la colección. No puedes hacer ambas cosas, esto es por diseño.

Además, no debe derivar de List<T>. Ver: Inheriting List<T> to implement collections a bad idea?

+0

Sé cómo se traduce. Todavía no veo ninguna razón por la cual no podamos combinar el primero con el segundo. – codymanix

+2

@codymanix: Porque no está en la especificación del idioma. – jason

+0

Me encantaría saber por qué esto fue votado negativamente. – jason

2

Si desea obtener algo como esta funcionalidad, considere hacer un argumento del constructor:

var x = new CustomList("Hello World") { 1, 2, 3 } 
+1

Pero en el caso donde tengo muchos argumentos pero quiero establecer solo unos pocos en la mayoría de los casos, esta no será la mejor solución – codymanix

Cuestiones relacionadas