为什么我可以将索引器应用于VB.Net中的ICollection,但不能应用于C#中 [英] Why can I apply an indexer to an ICollection in VB.Net, but not in C#
问题描述
当我遇到此问题时,正在使用Ionic Zip库将某些代码从VB.Net转换为C#:
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)
足够简单:
ZipEntry zipEntry1 = zipFile1.Entries[0];
我在C#上收到此错误:
I get this error on C#:
不能将带有[]的索引应用于类型的表达式 'System.Collections.Generic.ICollection'
Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.ICollection'
两者都使用相同版本的DLL,在两个zipFile1.Entries
上都是通用的ICollection
.
Both are using the same version of the DLL, on both zipFile1.Entries
is a generic ICollection
.
我已经在VB.Net上测试了以下内容,并且可以成功构建:
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
这不会建立:
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?
推荐答案
Bizarly,似乎VB对IEnumerable<T>
具有特殊支持,并且隐式提供了实际上调用
Bizarrely enough, it looks like VB has special support for IEnumerable<T>
and implicitly provides an indexer which actually calls Enumerable.ElementAtOrDefault
. ICollection<T>
extends IEnumerable<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#.
示例程序:
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
为Main生成的IL:
Generated IL for Main:
.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隐式地提供了此功能-使它看起来很危险 ,因为它可以很好地索引到不一定提供集合的集合中高效的索引操作.
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.
当然,如果您对ElementAtOrDefault
的操作感到满意,则可以自己打ElementAtOrDefault
.
Of course, you can call ElementAtOrDefault
yourself, if you're happy with what that does.
这篇关于为什么我可以将索引器应用于VB.Net中的ICollection,但不能应用于C#中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!