Подтвердить что ты не робот

Как проверить, является ли переменная некорректным 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 требует один аргумент типа"

Мне все равно, что это такое, я просто хочу знать, можете ли вы пропустить через переменную. Какой код следует использовать вместо этого?

4b9b3361

Ответ 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");