en gros, je construis un modèle T4 très générique et l'une des choses dont j'ai besoin pour le faire est de dire print variable.ToString()
. Cependant, je veux qu'il évalue les listes et les parcoure et imprime à la place ListItem.ToString()
Mon modèle T4 ne sait pas quel type variable
sera à l'avance, c'est pourquoi c'est si générique.
Mais mon code actuel qui est généré ressemble à ceci:
if(variable!=null)
if(variable is IEnumerable) //error here
foreach(var item in variable)
Write(item.ToString());
J'obtiens une erreur de compilation sur la ligne marquée pour "L'utilisation du type générique System.Generic.Collections.IEnumerable nécessite un argument de type"
Je ne me soucie pas vraiment de quel type il s'agit, je veux juste savoir si vous pouvez foreach à travers la variable. Quel code dois-je utiliser à la place?
Vous avez cependant déjà accepté une réponse, car le générique IEnumerable<T>
implémente le IEnumerable
non générique que vous pouvez simplement transtyper en cela.
// Does write handle null? Might need some sanity aswell.
var enumerable = variable as System.Collections.IEnumerable;
if (enumerable != null)
foreach(var item in enumerable)
Write(item);
else
Write(item);
Si vous voulez tester le non générique IEnumerable
alors vous devrez inclure un using System.Collections
directive en haut de votre fichier source.
Si vous souhaitez tester un IEnumerable<T>
d'une certaine sorte alors vous aurez besoin de quelque chose comme ça à la place:
if (variable != null)
{
if (variable.GetType().GetInterfaces().Any(
i => i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
// foreach...
}
}
Les autres réponses ont souligné la différence IEnumerable générique/non générique, mais je dois également souligner que vous voudrez également tester spécifiquement String car il implémente IEnumerable, mais je doute que vous souhaitiez le traiter comme une collection de caractères.
Depuis C # 7.0, vous pouvez également réaliser ceci ainsi:
if (variable is IEnumerable enumVar)
{
foreach (var e in enumVar)
{
...
}
}
Eh bien, un peu simple mais ... si vous avez seulement:
using System.Collections.Generic;
vous devrez peut-être ajouter:
using System.Collections;
Le premier définit IEnumerable<T>
et ce dernier définit IEnumerable
.
Dans général , sans type/interface de base non générique, cela nécessite GetType et une recherche récursive à travers la base types/interfaces.
Cependant , cela ne s'applique pas ici :-) Utilisez simplement le IEnumerable non générique (System.Collections.IEnumerable
), dont IEnumerable générique (System.Collections.Generic.IEnumerable<T>
) hérite.
Vous pouvez réellement tester directement la classe de base de tout type générique.
instance.GetGenericTypeDefinition() == typeof(IEnumerable<>)
Si vous ne vous souciez pas du type d'objet et que vous n'êtes pas dans la méthode générique dans C # 7.0+
if (item is IEnumerable<object> enumVar)
{
foreach (var e in enumVar)
{
e.ToString();
}
}
En C # <7,0
if (item is IEnumerable<object>)
{
var enumVar = item as IEnumerable<object>;
foreach (var e in enumVar)
{
e.ToString();
}
//or you can cast an array to set values,
//since IEnumerable won't let you, unless you cast to IList :)
//but array version here
//https://stackoverflow.com/a/9783253/1818723
}