为什么我可以通过索引访问KeyCollection/ValueCollection中的项目,即使它没有实现IList(Of Key)?

Tim*_*ter 10 .net c# vb.net compiler-errors visual-studio-2015

我注意到一个奇怪的VB.NET事情.从这个问题来看,我提供了一种方法来访问字典的键和值KeysCollection以及ValuesCollection通过索引来获取第一项.我知道它只是SortedDictionary因为正常Dictionary 没有被订购(嗯,你不应该依赖它的顺序).

这是一个简单的例子:

Dim sortedDict As New SortedDictionary(Of DateTime, String)
sortedDict.Add(DateTime.Now, "Foo")

Dim keys As SortedDictionary(Of DateTime, String).KeyCollection = sortedDict.Keys
Dim values As SortedDictionary(Of DateTime, String).ValueCollection = sortedDict.Values
Dim firstkey As DateTime = keys(0)
Dim firstValue As String = values(0)
Run Code Online (Sandbox Code Playgroud)

但我很惊讶问题的提问者说它不编译,而它编译并且对我有用而没有问题:

System.Diagnostics.Debug.WriteLine("Key:{0} Value:{1}", firstkey, firstValue) ' Key:04/29/2016 10:15:23 Value:Foo
Run Code Online (Sandbox Code Playgroud)

那么为什么我可以使用它,就像有一个索引器,如果实际上没有一个in SortedDictionary(Of?TKey,?TValue).KeyCollection-class,也没有ValueCollection.两者都实现了ICollection<T>哪个是父接口IList<T>.所以你可以循环它并且它有一个Count属性,但你不能像我上面那样通过索引访问项目.

请注意,它是一个新的控制台应用程序,内部没有扩展.我也不能去索引器的定义(也没有resharper).为什么它对我有用?

旁注:它在C#中不起作用.我得到了预期的编译器错误:

无法将带有[]的索引应用于"SortedDictionary.KeyCollection"类型的表达式

var dict = new SortedDictionary<DateTime, string>();
dict.Add(DateTime.Now, "Foo");
DateTime dt = dict.Keys[0]; // here
Run Code Online (Sandbox Code Playgroud)

这是编译VB.NET代码的屏幕截图:

在此输入图像描述

Che*_*hen 7

它调用Enumerable.ElementAtOrDefault,而不是索引器.

// [10 13 - 10 31]
IL_001f: ldloc.1      // keys
IL_0020: ldc.i4.0     
IL_0021: call         !!0/*valuetype [mscorlib]System.DateTime*/ [System.Core]System.Linq.Enumerable::ElementAtOrDefault<valuetype [mscorlib]System.DateTime>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0/*valuetype [mscorlib]System.DateTime*/>, int32)
IL_0026: stloc.2      // firstKey
Run Code Online (Sandbox Code Playgroud)

Visual Basic语言规范 11.21.3中记录了此行为:

每个可查询的集合类型(其元素类型是否T已具有默认属性)被视为具有以下常规形式的默认属性:

Public ReadOnly Default Property Item(index As Integer) As T
    Get
        Return Me.ElementAtOrDefault(index)
    End Get
End Property
Run Code Online (Sandbox Code Playgroud)

默认属性只能使用默认属性访问语法引用; 默认属性不能通过名称引用.例如:

Dim customers As IEnumerable(Of Customer) = ...
Dim customerThree = customers(2)

' Error, no such property
Dim customerFour = customers.Item(4)
Run Code Online (Sandbox Code Playgroud)

如果集合类型没有ElementAtOrDefault成员,则会发生编译时错误.

  • @TimSchmelter显然它是:[Visual Basic语言规范](https://msdn.microsoft.com/en-us/library/ms234437.aspx),11.21.3(学分转到[Stephen Cleary](http:// stackoverflow.com/users/263693/stephen-cleary)在https://social.msdn.microsoft.com/Forums/en-US/36492946-8560-4b03-8607-4a47a2b569d2/no-default-property-for-linked -list功能于CSHARP - 当 - 的 - 那里换VB-?论坛= netfxbcl) (2认同)