Was converting some code from VB.Net to C#, when I came across this, in some code using the Ionic Zip library:
Dim zipEntry1 As ZipEntry = zipFile1.Entries(0)
Simple enough:
ZipEntry zipEntry1 = zipFile1.Entries[0];
I get this error on C#:
Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.ICollection'
Both are using the same version of the DLL, on both zipFile1.Entries
is a generic ICollection
.
I have tested the below on VB.Net, and it builds successfullly:
Option Strict On
Option Explicit On
Imports Ionic.Zip
Module Module1
Sub Main()
Dim zipFile1 = ZipFile.Read("C:\test")
Dim zipEntry = zipFile1.Entries(0)
End Sub
End Module
This does not build:
using Ionic.Zip;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var zipFile1 = ZipFile.Read(@"C:\test");
var zipEntry = zipFile1.Entries[0];
}
}
}
Why does this happen, and is there a way around it?
Strictly viewed,
ICollection<T>
is an interface to an unordered collection of elements (more precisely, a collection whose elements cannot individually be accessed by their index). That is just by definition.But you can still use LINQ's
ElementAt(int index)
extension method. That would just iterate through all elementsindex
times every time you call it (so it is generally slower).NOTE:
ICollection<T>
is not to be confused withCollection<T>
. The latter implementsIList<T>
(among other things), which by definition does specify that each element can be accessed by its index.Bizarrely enough, it looks like VB has special support for
IEnumerable<T>
and implicitly provides an indexer which actually callsEnumerable.ElementAtOrDefault
.ICollection<T>
extendsIEnumerable<T>
, so the same facility exists there.ICollection<T>
doesn't provide a "real" indexer, hence the problem when you try using it from C#.Sample program:
Generated IL for Main:
I find it very odd that VB provides this implicitly - it's really dangerous to make it look like it's fine to index into a collection which doesn't necessarily supply an efficient indexing operation.
Of course, you can call
ElementAtOrDefault
yourself, if you're happy with what that does.VB has long had the idea of a default member for it's classes, which for collections is always the member Item().