Как проверить, является ли переменная некорректным IEnumerable
В основном я создаю очень общий шаблон T4, и одна из вещей, которые мне нужны, это сказать print variable.ToString()
. Тем не менее, я хочу, чтобы он оценивал списки и пропускал их через них, а вместо этого печатал ListItem.ToString()
. Мой шаблон T4 не знал, какой тип variable
будет раньше времени, поэтому это так общее.
Но мой текущий код, который генерируется, выглядит следующим образом:
if(variable!=null)
if(variable is IEnumerable) //error here
foreach(var item in variable)
Write(item.ToString());
Я получаю ошибку компилятора в отмеченной строке для "Использование родового типа System.Generic.Collections.IEnumerable требует один аргумент типа"
Мне все равно, что это такое, я просто хочу знать, можете ли вы пропустить через переменную. Какой код следует использовать вместо этого?
Ответы
Ответ 1
Однако вы уже приняли ответ, так как generic IEnumerable<T>
реализует не общий IEnumerable
, который вы можете просто применить к нему.
// 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);
Ответ 2
Если вы хотите протестировать не общий IEnumerable
, вам нужно включить директиву using System.Collections
наверху исходного файла.
Если вы хотите протестировать IEnumerable<T>
, вам понадобится что-то вроде этого:
if (variable != null)
{
if (variable.GetType().GetInterfaces().Any(
i => i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
// foreach...
}
}
Ответ 3
В других ответах указывается общая/неоригинальная разница IEnumerable, но я должен также указать, что вы также захотите проверить для String именно потому, что она реализует IEnumerable, но я сомневаюсь, что вы захотите рассматривать ее как коллекцию символов.
Ответ 4
Ну, несколько просто, но... если у вас есть только:
using System.Collections.Generic;
вам может потребоваться добавить:
using System.Collections;
Первый определяет IEnumerable<T>
, а последний определяет IEnumerable
.
Ответ 5
Начиная с С# 7.0, вы также можете достичь этого так:
if (variable is IEnumerable enumVar)
{
foreach (var e in enumVar)
{
...
}
}
Ответ 6
В общем случае без базового типа/интерфейса базового типа для этого требуется GetType и рекурсивный поиск по базовым типам/интерфейсы.
Однако это не применяется здесь:-)
Просто используйте не общий IEnumerable (System.Collections.IEnumerable
), из которого общий IEnumerable (System.Collections.Generic.IEnumerable<T>
) наследует.
Ответ 7
Фактически вы можете проверить базовый класс любого общего типа.
instance.GetGenericTypeDefinition() == typeof(IEnumerable<>)
Ответ 8
Если вас не волнует тип объекта, и вы не используете общий метод в С# 7. 0+
if (item is IEnumerable<object> enumVar)
{
foreach (var e in enumVar)
{
e.ToString();
}
}
В С# & lt; 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
}
Ответ 9
Это старый вопрос, но я хотел показать альтернативный метод определения того, является ли SomeType
IEnumerable
:
var isEnumerable = (typeof(SomeType).Name == "IEnumerable`1");