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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With