LINQ funciona com IEnumerable?

87

Tenho uma classe que implementa IEnumerable, mas não implementa IEnumerable<T>. Não posso mudar esta classe e não posso usar outra classe em vez dela. Como eu entendi do MSDN, LINQ pode ser usado se a classe for implementadaIEnumerable<T> . Tentei usar instance.ToQueryable(), mas ainda não habilita os métodos LINQ. Eu sei com certeza que esta classe pode conter instâncias de apenas um tipo, então a classe poderia implementar IEnumerable<T>, mas simplesmente não o faz. Então, o que posso fazer para consultar essa classe usando expressões LINQ?

Bogdan Verbenets
fonte
Sem lançar o IEnumerable, em vez de todos os métodos linq, você verá apenas 8 métodos: AsQueryable, Cast <>, Equals, GetEnumerator, GetHashCode, GetType, OfType <>, ToString
ShawnFeatherly

Respostas:

134

Você pode usar Cast<T>()ou OfType<T>para obter uma versão genérica de um IEnumerable que oferece suporte total ao LINQ.

Por exemplo.

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

Ou se você não sabe que tipo ele contém, você sempre pode fazer:

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

Se o seu não genérico IEnumerablecontém objetos de vários tipos e você está interessado apenas em, por exemplo. as strings que você pode fazer:

IEnumerable<string> strings = objects.OfType<string>();
DeCaf
fonte
2
Todos os dias, aprendo algo novo sobre o LINQ. A cada dia, eu amo isso mais e mais.
João Mendes
11

Sim pode. Você só precisa usar a Cast<T>função para convertê-la em digitada IEnumerable<T>. Por exemplo:

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

Agora e2é um IEnumerable<T>e pode trabalhar com todas as funções do LINQ.

JaredPar
fonte
3

Você também pode usar a sintaxe de compreensão de consulta do LINQ, que converte para o tipo da variável de intervalo ( itemneste exemplo) se um tipo for especificado:

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

O efeito é idêntico à solução de @JaredPar; consulte 7.16.2.2: Tipos explícitos de variáveis ​​de intervalo na especificação da linguagem C # para obter detalhes.

TrueWill
fonte