为什么我可以申请一个索引到VB.Net的ICollection的,但不是在C#(Why can I

2019-08-20 04:06发布

从VB.Net转换部分代码为C#,当我遇到这个来了,在使用离子邮编库一些代码:

Dim zipEntry1 As ZipEntry = zipFile1.Entries(0)

很简单:

ZipEntry zipEntry1 = zipFile1.Entries[0];

我得到C#这样的错误:

可以不适用[]索引,以类型的“了System.Collections.Generic.ICollection”的表达式

两者都使用DLL的相同版本,在两个zipFile1.Entries是一个通用ICollection

我已经测试以下的VB.Net,它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

这不建:

using Ionic.Zip;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var zipFile1 = ZipFile.Read(@"C:\test");
            var zipEntry = zipFile1.Entries[0];
        }
    }
}

为什么会这样,是有办法解决它?

Answer 1:

奇怪的是,它看起来像VB有特殊支持IEnumerable<T>和隐式地提供这实际上是调用一个索引Enumerable.ElementAtOrDefaultICollection<T>延伸IEnumerable<T>因此同样存在设施那里。 ICollection<T>当您尝试使用它从C#不提供“真正”的索引,因此这个问题。

样例程序:

Option Strict On

Public Class Test
    Public Shared Sub Main(args As String())
      Dim x as System.Collections.Generic.ICollection(Of String) = args
      Console.WriteLine(x(0))
    End Sub
End Class

产生IL为主营:

.method public static void  Main(string[] args) cil managed
{
  .entrypoint
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       15 (0xf)
  .maxstack  2
  .locals init 
      (class [mscorlib]System.Collections.Generic.IEnumerable`1<string> V_0)
  IL_0000:  ldarg.0
  IL_0001:  stloc.0
  IL_0002:  ldloc.0
  IL_0003:  ldc.i4.0
  IL_0004:  call       !!0
     [System.Core]System.Linq.Enumerable::ElementAtOrDefault<string>(
        class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>,
        int32)
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000e:  ret
} // end of method Test::Main

我觉得奇怪,VB提供了这种含蓄-这是非常危险的,使它看起来像它的优良指数为收集这并不一定提供一个高效的索引操作。

当然,你可以调用ElementAtOrDefault自己,如果你满意的是什么一样。



Answer 2:

严格观察, ICollection<T>是元素的无序集合的接口(更精确地,收集其元素不能单独通过索引来访问)。 这仅仅是定义

但你仍然可以使用LINQ的ElementAt(int index)扩展方法。 这将刚刚经历的所有元素迭代index次,每次调用它(所以它一般是慢)。

注: ICollection<T>不与混淆Collection<T> 后者实现IList<T>除其他外),其通过定义指定每个元件可以通过它的索引来访问。



Answer 3:

VB早已为它的类默认成员 ,这对于集合总是成员项目 ()的想法。



Answer 4:

zipFile1.Entries(0)调用所谓默认查询索引 ,这是在所定义的一个鲜为人知的特征VB语言规范 :

默认查询索引

每一个可查询集合类型,其元素类型是T和不已经有一个默认的属性被认为具有以下一般形式的默认属性:

 Public ReadOnly Default Property Item(index As Integer) As T Get Return Me.ElementAtOrDefault(index) End Get End Property 


文章来源: Why can I apply an indexer to an ICollection in VB.Net, but not in C#