2009-12-09 11 views
12

que cuando se declara un parámetro como ICollection e instancia del objeto en una lista, ¿por qué no podemos retrive los índices? es decir,¿Por qué el índice ICollection no funciona cuando se crea una instancia?

ICollection<ProductDTO> Products = new List<ProductDTO>(); 
Products.Add(new ProductDTO(1,"Pen")); 
Products.Add(new ProductDTO(2,"Notebook"));

Entonces, esto no funcionará:

ProductDTO product = (ProductDTO)Products[0];

Cuál es la parte que me falta?
[Sí, podemos utilizar la lista como una declaración que puede funcionar, pero no quieren declarar como lista, como:

List<ProductDTO> Products = new List<ProductDTO>();

]

+0

¿Quieres decir 'Productos .Add (nuevo ProductDTO (1, "Pen")); '? –

+0

¿Es este el ejemplo real? Ni List ni ICollection tienen una sobrecarga para el método Add que toma dos argumentos? –

Respuesta

20

La interfaz ICollection no declara una indexador, por lo que no se puede utilizar la indexación a buscar elementos a través de una referencia de ese tipo.

Usted tal vez podría intentar IList, que añade algunas funciones más, sin dejar de ser abstracto. Por supuesto, esto puede afectar otras decisiones de diseño, así que lo vería con cuidado.

+0

Cuando dices la decisión de diseño. ¿Qué quieres decir? ¿Qué es mejor usar IList o ICollection? –

+1

@Inanikian No hay "lo mejor"; depende del contexto Si debe usar métodos en IList , por ejemplo, si necesita indizar/ordenar, IList puede ser el mejor tipo de interfaz para requerir. Si, por otro lado, solo te importa contar, agregar, eliminar y enumerar elementos, pero nunca por índice, y no quieres imponer un requisito de funcionalidad adicional en una clase para tener un indexador y todas las demás funcionalidades. implicado por IList que no usaría de todos modos, entonces podría ser mejor requerir solo lo que necesita, por ejemplo, ICollection (o incluso IEnumerable , si no está modificando nada). –

7

ICollection no define un indexador.

ICollection Non-Generic

ICollection Generic

+0

Su enlace es a ICollection no genérica, debe re-apuntar a la forma genérica @ http://msdn.microsoft.com/en-us/library/92t2ye13.aspx – jball

+0

@BasicallyMoney veces respuestas cortas son todo lo que se necesita. – jball

+1

Las respuestas rápidas son más rápidas de leer.Y a los usuarios no les gusta leer, ¿recuerdas? :) –

4

El problema básico es que ICollection no define un índice. Para la Lista, esto se hace mediante la implementación de IList.

Prueba esto:

IList<ProductDTO> Products = new List<ProductDTO>(); 

Alternatly, puede seguir usando ICollection y convertir a un array cuando se necesita acceder a los elementos por el índice:

ICollection<ProductDTO> Products = new List<ProductDTO>();   
ProductDTO z = Products.ToArray()[0]; 
+0

'ICollection <>' no tiene un método ToArray, eso es 'List <>' solamente. Necesitas 'CopyTo' en su lugar. – thecoop

+5

Depende de qué versión de .net. ToArray() es un método de extensión del 3.x framework .net. –

2

entonces esto va a trabajar:

ProductDTO product = ((IList<ProductDTO>)Products)[0]; 

la razón es que el compilador evalúa el valor izquierdo , que es la variable en el lado izquierdo de '=', para saber qué métodos y propiedades que sabe que puede acceder en tiempo de compilación. Esto se conoce como tipos estáticos, y se asegura de que un miembro de objeto se puede acceder directamente en tiempo de ejecución por estáticamente sabiendo que el miembro es siempre accesible.

+1

Esto elimina el beneficio de trabajar con la abstracción proporcionada por una interfaz: si posteriormente se cambia a Productos que no sea la Lista , el código anterior se rompe porque hace una suposición sobre el tipo subyacente al realizar el reparto. –

+0

Sí, pero soluciona la única declaración de la que se quejaba OP. –

+2

¡Usted y yo tenemos diferentes definiciones de la palabra ** arreglos **! ;-) –

17

mediante LINQ, se puede hacer esto:

ProductDTO product = (ProductDTO)Products.ElementAt(0); 
1

El uso de LINQ, puede acceder a un elemento en un ICollection <> a un índice específico de esta manera:

myICollection.AsEnumerable().ElementAt(myIndex); 
Cuestiones relacionadas