Matthew
Matthew

Reputation: 10444

How to check if IEnumerable is a List?

Given an IEnumerable, how can I check if its type is List?

Given an IEnumerable, I want to perform List methods, but if it's a List already I will simply cast it rather that using .ToList()

Upvotes: 2

Views: 1644

Answers (6)

supercat
supercat

Reputation: 81337

I've often wished for a bigger selection of collection-related interfaces, especially ICountableEnumerable and IReadableByIndex. The former could have been added in the design of .Net without adding extra code by implementors; the former would probably have required the addition of a GetByIndex method to avoid conflicts with the read/write indexer present in a full IList, but would IMHO still have been a worthwhile addition since it could be contravariant.

As it is, it's possible that an object may be a generic IList but not very well usable for your purposes because it may be an IList of a type which is derived from the type you're expecting. For example, if your routine were expecting an IEnumerable(Of Car) but were passed an IList(Of HondaCivic), it would be nice if you could use its read-by-index function. If IList(Of T) inherited from IReadableByIndex(Of T), as described above, an IList(Of HondaCivic) could be cast to an IReadableByIndex(Of Car). Unfortunately, such a cast isn't possible with a read-write interface.

Still, using a generic routine to process the list may make it possible to avoid an unnecessary conversion even in such case. The following short VB class illustrates:

Class GenericTest
    Class myThing
        Public Value As String
        Sub New(ByVal X As String)
            Value = X
        End Sub
    End Class
    Class myDerived
        Inherits myThing
        Sub New(ByVal x As String)
            MyBase.New(x)
        End Sub
    End Class
    Shared Sub ReversePrint(Of T As myThing)(ByVal theList As IEnumerable(Of T))
        Dim castAsList As IList(Of T) = TryCast(theList, IList(Of T))
        If castAsList Is Nothing Then
            castAsList = theList.ToList
            Debug.Print("Converting to list")
        Else
            Debug.Print("List was good")
        End If
        For i As Integer = castAsList.Count - 1 To 0 Step -1
            Debug.Print(castAsList(i).Value.ToString)
        Next
    End Sub
    Shared Sub Test()
        Dim myList As New List(Of myDerived)
        For i As Integer = 1 To 5
            myList.Add(New myDerived("Item " & i.ToString))
        Next
        ReversePrint(myList)
        ReversePrint(Of myThing)(myList)
    End Sub
End Class

The ReversePrint function casts or converts an IEnumerable to an IList and outputs it in reverse order. Note that the routine is really "expecting" an IEnumerable(Of myThing), but accepts its parameter as an IEnumerable(Of T). Thus, if the compiler knows that it implements IEnumerable(Of myDerived), it can offer up MyDerived as a type parameter. When doing so, the object can be cast to an IList(of MyDerived). If one prevents the generic parameter from conforming to the original object, the object will be passed to the routine just fine, but the try-typecast won't work and thus it will be necessary to convert the item to an IList conforming to the passed-in type parameter.

PS--One of my wish-list items for .Net 5.0 would be the ability for an interface to specify a default implementation of a method for use in case a class which is supposed to implement a method doesn't provide one. This could allow Microsoft to have IList inherit from a contravariant IReadableByIndex interface (and possibly covariant IWritableByIndex and IAppendable interfaces) without breaking existing code.

Upvotes: 0

Oded
Oded

Reputation: 499382

Use the is operator to test the type of the variable.

if(myIEnumerable is IList)
{
   // it is a List (may still need casting in order to use List specific methods)
}

Upvotes: 6

Farshid Zaker
Farshid Zaker

Reputation: 1990

You can use is or as operators.

Upvotes: 2

Michael Kennedy
Michael Kennedy

Reputation: 3380

Couple of ways:

List<int> list = myColl as List<int>;
if (list != null) // ...

or

if (myColl is List<int>) // ...

or

if (myColl.GetType() == typeof(List<int>) // ...

Upvotes: 1

Achim
Achim

Reputation: 15722

List list = (yourEnumerable as List) ?? yourEnumerable.ToList();

Upvotes: 3

David Ly
David Ly

Reputation: 31606

var myList = myIEnumerable as List ?? myIEnumerable.ToList();

or

var myList = (myIEnumerable as List<Type>) ?? myIEnumerable.ToList();

Upvotes: 2

Related Questions