nayef harb
nayef harb

Reputation: 753

Importing System.Linq solves "Class cannot be indexed" error

I have the following code which is failing to compile:

Dim ContentSent As HashSet(Of String) = New HashSet(Of String)(SubscriberContent.ContentIdSent.Split(","))
content = New Content
' The next line causes causing the error
content = contentCollection.Find(Function(x) x.CntId = Convert.ToInt32(ContentSent(0)))

The error it gets is:

Class cannot be indexed because it has no default property

That makes sense. The weird thing is, when I import System.Linq the compilation error disappears.

For a more simple example, this code gets the error:

Imports System
Imports System.Collections.Generic

Module MyModule
    Public Sub Main()
        Dim x As IEnumerable(Of Integer) = {0, 1, 2, 3}
        Dim item As Integer = x(3) ' Gets error on this line
        Console.WriteLine(item)
    End Sub
End Module

But this works:

Imports System
Imports System.Collections.Generic
Imports System.Linq  ' This is the only difference!

Module MyModule
    Public Sub Main()
        Dim x As IEnumerable(Of Integer) = {0, 1, 2, 3}
        Dim item As Integer = x(3) 
        Console.WriteLine(item)  ' Outputs "3"
    End Sub
End Module

Why does importing the System.Linq namespace solve that particular error? It doesn't seem like it should.

Upvotes: 0

Views: 340

Answers (1)

TnTinMn
TnTinMn

Reputation: 11801

Presumably the offending item is: ContentSent(0)

It appears that once you Import System.Linq, that VB automatically uses the extension method ElementAtOrDefault as a "pseudo default" indexer for ContentSent.

You can see this for yourself, if you backspace over the index and observe the Intellisense display.


@StevenDoggart's comment prompted me to revisit this issue. This behavior by VB is specified in the Visual Basic Language Specification.

This particular VB feature is known as the Default Query Indexer.

Default Query Indexer

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.

Upvotes: 1

Related Questions