DrDonut
DrDonut

Reputation: 904

.Where method not defined on generic typed list?

When I try to use the .Where() method on a list, this does method does not seem to be defined if the list is of a generic type:

In my program, I have a class called Warning, and in another class, a list of warnings, defined as:

Dim warningList As List(Of Warning)

When I try to manipulate this list as:

Dim item = warningList.Where(Function(x) x.GetName() = "Foo").FirstOrDefault()

This works completely fine, but when I try it like this:

Dim itemList
if(type = "Warning") Then 'Please note that this condition is true...
    itemList = warningList
End If

Dim item = itemList.Where(Function(x) x.GetName() = "Foo").FirstOrDefault()

I get an exception, stating that method .Where() is not defined for class Warning

Can anybody tell me why this is? Thank you!

Upvotes: 0

Views: 61

Answers (1)

Tim Schmelter
Tim Schmelter

Reputation: 460138

Now that you've edited your question it's clear.

You declare itemList without a type, so it's Object implicitly(in VB.NET with option strict set to Off which i strongly recommend against).

Now that you have declared a variable of type Object you can asssign any type to it. But you would have to cast it back to its real type List(Of Warning) to be able to use list or LINQ methods(which extend IEnumerable(Of T).

But instead declare it with the correct type:

Dim itemList As List(Of Warning)
if(type = "Warning") Then
    itemList = warningList
End If

Dim item = itemList.Where(Function(x) x.GetName() = "Foo").FirstOrDefault()

Including to comment to explain why Warning is not related to this problem:

That's not the real code. If warningList is really a List(Of Warning) you should be able to use Enumerable.Where(if LINQ is imported). The fact that you assign this instance to another variable (on declaration) doesn't change anything because that variable's type is also a List(Of Warning). So itemList.Where should work too. Warning has nothing to do with it because the type which is extended by Where is IEnumerable(Of T), T can be any type(even Object). Since List(Of T) implements IEnumerable(Of T) you can use Enumerable.Where on any list (or array).


If you actually have multiple types and Warning is just one of it, you should implement a common interface. Here's an example:

Public Enum NotificationType
    Warning
    Info
    [Error]
End Enum

Public Interface INamedNotification
    ReadOnly Property Type As NotificationType
    Property Name As string
End Interface

Public Class Warning
    Implements INamedNotification
    Public Sub New( name As String )
        Me.Name = name
    End Sub
    Public Property Name As String Implements INamedNotification.Name
    Public ReadOnly Property Type As NotificationType Implements INamedNotification.Type
        Get
            Return NotificationType.Warning
        End Get
    End Property
End Class

Now you can declare a List(Of INamedNotification) and fill it with whatever implements this interface, like the Warning class:

Dim notificationList As List(Of INamedNotification)
if type = "Warning" Then 
    itemList = warningList
Else If type = "Info"
    itemList = infoList  
End If

Dim item = notificationList.Where(Function(x) x.Name = "Foo").FirstOrDefault()

Upvotes: 1

Related Questions