LINQ работает с IEnumerable?

87

У меня есть класс, который реализует IEnumerable, но не реализует IEnumerable<T>. Я не могу изменить этот класс и не могу использовать вместо него другой класс. Как я понял из MSDN, LINQ можно использовать, если класс реализуетIEnumerable<T> . Я пробовал использовать instance.ToQueryable(), но методы LINQ все еще не включены. Я точно знаю, что этот класс может содержать экземпляры только одного типа, поэтому класс можно реализовать IEnumerable<T>, но это не так. Итак, что я могу сделать, чтобы запросить этот класс с помощью выражений LINQ?

Богдан Вербенец
источник
Без преобразования IEnumerable вместо всех методов linq вы увидите только 8 методов: AsQueryable, Cast <>, Equals, GetEnumerator, GetHashCode, GetType, OfType <>, ToString
ShawnFeatherly

Ответы:

135

Вы можете использовать Cast<T>()или, OfType<T>чтобы получить универсальную версию IEnumerable, полностью поддерживающую LINQ.

Например.

IEnumerable objects = ...;
IEnumerable<string> strings = objects.Cast<string>();

Или, если вы не знаете, какой тип он содержит, вы всегда можете сделать:

IEnumerable<object> e = objects.Cast<object>();

Если ваш неуниверсальный IEnumerableсодержит объекты различных типов, и вас интересуют только, например, строки, которые вы можете делать:

IEnumerable<string> strings = objects.OfType<string>();
Без кофеина
источник
2
Каждый день я узнаю что-то новое о LINQ. С каждым днем ​​я люблю это все больше и больше.
Жуан Мендес,
11

Да, оно может. Вам просто нужно использовать Cast<T>функцию, чтобы преобразовать его в типизированный IEnumerable<T>. Например:

IEnumerable e = ...;
IEnumerable<object> e2 = e.Cast<object>();

Теперь e2есть IEnumerable<T>и может работать со всеми функциями LINQ.

ДжаредПар
источник
3

Вы также можете использовать синтаксис понимания запросов LINQ, который приводит к типу переменной диапазона ( itemв этом примере), если тип указан:

IEnumerable list = new ArrayList { "dog", "cat" };

IEnumerable<string> result =
  from string item in list
  select item;

foreach (string s in result)
{
    // InvalidCastException at runtime if element is not a string

    Console.WriteLine(s);
}

Эффект идентичен решению @ JaredPar; подробности см. в 7.16.2.2: Явные типы переменных диапазона в спецификации языка C #.

TrueWill
источник