Как проверить, является ли IEnumerable списком? - PullRequest
2 голосов
/ 02 июня 2011

Учитывая IEnumerable, как я могу проверить, является ли его тип List?

Учитывая IEnumerable, я хочу выполнить методы List, но если это уже List, я просто приведу его, а не .ToList ()

Ответы [ 6 ]

4 голосов
/ 02 июня 2011

Используйте оператор is для проверки типа переменной.

if(myIEnumerable is IList)
{
   // it is a List (may still need casting in order to use List specific methods)
}
2 голосов
/ 02 июня 2011

Вы можете использовать is или as операторов.

2 голосов
/ 02 июня 2011
List list = (yourEnumerable as List) ?? yourEnumerable.ToList();
2 голосов
/ 02 июня 2011
var myList = myIEnumerable as List ?? myIEnumerable.ToList();

или

var myList = (myIEnumerable as List<Type>) ?? myIEnumerable.ToList();
1 голос
/ 02 июня 2011

Пара способов:

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

или

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

или

if (myColl.GetType() == typeof(List<int>) // ...
0 голосов
/ 04 июня 2011

Мне часто хотелось большего выбора интерфейсов, связанных с коллекцией, особенно ICountableEnumerable и IReadableByIndex. Первый можно было бы добавить в дизайн .Net без добавления дополнительного кода разработчиками; первый, вероятно, потребовал бы добавления метода GetByIndex, чтобы избежать конфликтов с индексатором чтения / записи, присутствующим в полном IList, но ИМХО по-прежнему было бы полезным добавлением, поскольку это могло бы быть противоречивым.

В действительности, возможно, что объект может быть универсальным IList, но не очень хорошо применимым для ваших целей, потому что это может быть IList типа, который получен из ожидаемого вами типа. Например, если ваша процедура ожидала IEnumerable (Of Car), но ей был передан IList (Of HondaCivic), было бы неплохо, если бы вы могли использовать функцию чтения по индексу. Если IList (Of T) унаследован от IReadableByIndex (Of T), как описано выше, IList (Of HondaCivic) может быть преобразован в IReadableByIndex (Of Car). К сожалению, такое преобразование невозможно с интерфейсом чтения-записи.

Тем не менее, использование универсальной подпрограммы для обработки списка может позволить избежать ненужного преобразования даже в таком случае. Следующий короткий класс VB иллюстрирует:

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

Функция ReversePrint преобразует или преобразует IEnumerable в IList и выводит его в обратном порядке. Обратите внимание, что процедура действительно «ожидает» IEnumerable (Of myThing), но принимает ее параметр как IEnumerable (Of T). Таким образом, если компилятор знает, что он реализует IEnumerable (Of myDerived), он может предложить MyDerived в качестве параметра типа. При этом объект может быть приведен к IList (из MyDerived). Если кто-то не позволяет универсальному параметру соответствовать исходному объекту, объект будет нормально передаваться в подпрограмму, но попытка ty-type не будет работать, и, следовательно, будет необходимо преобразовать элемент в IList, соответствующий переданному параметр типа.

PS - Одним из пунктов моего списка желаний для .Net 5.0 была бы возможность для интерфейса указать реализацию по умолчанию метода для использования в случае, если класс, который должен реализовать метод не обеспечивает один. Это может позволить Microsoft иметь наследование IList от контравариантного интерфейса IReadableByIndex (и, возможно, ковариантных интерфейсов IWritableByIndex и IAppendable) без нарушения существующего кода.

...