开发者

How to check if IEnumerable is a List?

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

Given an IEnume开发者_JS百科rable, I want to perform List methods, but if it's a List already I will simply cast it rather that using .ToList()


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)
}


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


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

or

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


You can use is or as operators.


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>) // ...


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜