为什么我可以通过索引访问KeyCollection / ValueCollection中的项目,即使它不实现IList(键)? [英] Why can I access an item in KeyCollection/ValueCollection by index even if it doesn't implement IList(Of Key)?

查看:209
本文介绍了为什么我可以通过索引访问KeyCollection / ValueCollection中的项目,即使它不实现IList(键)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到一个奇怪的VB.NET事情。来自

解决方案

$ c> 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

此行为记录在 Visual Basic语言规范,11.21.3:


其元素类型为 T 且尚未具有默认属性的每个可查询集合类型都被视为具有默认属性具有以下一般形式:

 公共ReadOnly默认属性项(索引为Integer) 
Get
返回Me.ElementAtOrDefault(index)
End Get
结束属性

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

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

'错误,没有这样的属性
Dim customerFour = customers.Item(4)

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



I've noticed a strange VB.NET thing. Coming from this question I've provided a way to access keys and values of dictionaries' KeysCollection and ValuesCollection via index to get, say, the first item. I know that it makes only sense in a SortedDictionary since a normal Dictionary is not ordered (well, you should not rely on its order).

Here's a simple example:

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)

But I was surprised that the question's asker said that it doesn't compile whereas it compiles and works for me without a problem:

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

So why can I use it like there was an indexer if there isn't actually one in SortedDictionary(Of TKey, TValue).KeyCollection-class and also none in the ValueCollection. Both implement ICollection<T> which is the parent interface of IList<T>. So you can loop it and it has a Count property, but you can't access items via index as I do above.

Note that it's a fresh console application with no extensions inside. I can't go to the definition of the indexer either(also not with resharper). Why does it work for me?

Side-note: it doesn't work in C#. I get the expected compiler error:

Cannot apply indexing with [] to an expression of type 'SortedDictionary.KeyCollection'

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

Here's a screenshot of the compiling VB.NET code:

解决方案

It invokes Enumerable.ElementAtOrDefault, not the indexer.

// [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

This behavior is documented in the Visual Basic Language Specification, 11.21.3:

Every queryable collection type whose element type is T and does not already have a default property is considered to have a default property of the following general form:

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

The default property can only be referred to using the default property access syntax; the default property cannot be referred to by name. For example:

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

' Error, no such property
Dim customerFour = customers.Item(4)

If the collection type does not have an ElementAtOrDefault member, a compile-time error will occur.

这篇关于为什么我可以通过索引访问KeyCollection / ValueCollection中的项目,即使它不实现IList(键)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆