LINQ fonctionne-t-il avec IEnumerable?

87

J'ai une classe qui implémente IEnumerable, mais ne l'implémente pas IEnumerable<T>. Je ne peux pas changer cette classe, et je ne peux pas utiliser une autre classe à la place. Comme je l'ai compris de MSDN, LINQ peut être utilisé si la classe implémenteIEnumerable<T> . J'ai essayé d'utiliser instance.ToQueryable(), mais cela n'active toujours pas les méthodes LINQ. Je sais avec certitude que cette classe peut contenir des instances d'un seul type, donc la classe pourrait implémenter IEnumerable<T>, mais ce n'est tout simplement pas le cas. Alors, que puis-je faire pour interroger cette classe à l'aide d'expressions LINQ?

Bogdan Verbenets
la source
Sans lancer le IEnumerable, au lieu de toutes les méthodes linq, vous ne verrez que 8 méthodes: AsQueryable, Cast <>, Equals, GetEnumerator, GetHashCode, GetType, OfType <>, ToString
ShawnFeatherly

Réponses:

134

Vous pouvez utiliser Cast<T>()ou OfType<T>pour obtenir une version générique d'un IEnumerable qui prend entièrement en charge LINQ.

Par exemple.

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

Ou si vous ne savez pas quel type il contient, vous pouvez toujours faire:

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

Si votre non-générique IEnumerablecontient des objets de différents types et que vous n'êtes intéressé que par ex. les chaînes que vous pouvez faire:

IEnumerable<string> strings = objects.OfType<string>();
Café décaféiné
la source
2
Chaque jour, j'apprends quelque chose de nouveau sur LINQ. Chaque jour, je l'aime de plus en plus.
João Mendes
11

Oui il peut. Il vous suffit d'utiliser la Cast<T>fonction pour le convertir en fichier typé IEnumerable<T>. Par exemple:

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

Maintenant e2est un IEnumerable<T>et peut fonctionner avec toutes les fonctions LINQ.

JaredPar
la source
3

Vous pouvez également utiliser la syntaxe de compréhension de requête de LINQ, qui convertit le type de la variable de plage ( itemdans cet exemple) si un type est spécifié:

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

L'effet est identique à la solution de @ JaredPar; voir 7.16.2.2: Types de variables de plage explicites dans la spécification du langage C # pour plus de détails.

TrueWill
la source