views:

459

answers:

4

When we declare a parameter as ICollection and instantiated the object as List, why we can't retrive the indexes? i.e.

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

Then, this will not work:

ProductDTO product = (ProductDTO)Products[0];

What is the bit I am missing?
[Yes, we can use List as declaration an it can work, but I don't want to declare as list, like:

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

]

+6  A: 

ICollection does not define an indexer.

ICollection Non-Generic

ICollection Generic

ChaosPandion
Your link is to the non-generic ICollection, you should repoint it to the generic form @ http://msdn.microsoft.com/en-us/library/92t2ye13.aspx
jball
@BasicallyMoney Sometimes short answers are all that's needed.
jball
Terse answers are faster to read. And users don't like to read, remember? :)
Kyralessa
+8  A: 

The ICollection interface doesn't declare an indexer, so you can't use indexing to fetch elements through a reference of that type.

You could perhaps try IList, which adds some more functionality, while still being abstract. Of course, this may impact other design decisions so I would look at this carefully.

Chris W. Rea
+3  A: 

The basic problem is that ICollection doesn't define an index. For the List this is done by the implementation of IList.

Try this:

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

Alternatly, you can keep using ICollection and convert to an array when you need to access the elements by the index:

ICollection<ProductDTO> Products = new List<ProductDTO>();        
ProductDTO z = Products.ToArray()[0];
Stephen M. Redd
`ICollection<>` does not have a ToArray method on it - that's `List<>` only. You need `CopyTo` instead.
thecoop
Depends on which version of .net. ToArray() is an extension method from the 3.x .net framework.
Stephen M. Redd
+1  A: 

Then this will work:

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

The reason is that the compiler evaluates the lvalue, that is the variable on the left side of '=', to find out which methods and properties it knows it can access at compile-time. This is known as static typing, and ensures that an object member can be accessed directly at runtime by statically knowing that the member is always reachable.

Cecil Has a Name
This eliminates the benefit of working with the abstraction provided by an interface: if Products is later changed to be something other than List<ProductDTO>, the code above is broken because it makes an assumption about underlying type when performing the cast.
Chris W. Rea
Yes, but it fixes the single statement the OP complained about.
Cecil Has a Name
You and I have different definitions of the word **fixes**! ;-)
Chris W. Rea
You need to read my comment one more time: It changes a *single* statement. I never said I fixed the *cause of the problem*. You can't always call it a spade for its looks, a so-called *fix* in the programming world.
Cecil Has a Name