Why can I access an item in KeyCollection/ValueCollection by index even if it doesn't implement IList(Of Key)?

后端 未结 2 528
Happy的楠姐
Happy的楠姐 2020-12-04 02:00

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 Values

相关标签:
2条回答
  • 2020-12-04 02:01

    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.

    0 讨论(0)
  • 2020-12-04 02:13

    There is a considerable performance cost when we use Enumerable.ElementAtOrDefault or Enumerable.ElementAt. Unless the source implements IList(of T) interface, Linq does not have shorter route to get to the element at the specified index. So it iterates each element untill iteration count reaches to value of specified index. No magic. Enumerable. Count() has the same story except in this case ICollection interface if implemented by source, Linq grabs it otherwise iteration untill the last element is required to produce Count. I don't know why Vb.net allowing it implicitly because chances are that cases like this will remain unnoticed until I face serious performance issue. Dictionary only implements ICollection not IList. I think one needs to be careful with Vb.net as it is not as strictly typed language as C#.

    0 讨论(0)
提交回复
热议问题