Определите, имеет ли тип коллекции тип IEnumerable <T>

Как определить, имеет ли объект тип IEnumerable <T> ?

код:

namespace NS {
    class Program {
        static IEnumerable<int> GetInts() {
            yield return 1;
        }
        static void Main() {
            var i = GetInts();
            var type = i.GetType();
            Console.WriteLine(type.ToString());
        }
    }
}

Вывод:

NS.1.Program+<GetInts>d__0

Если я изменю GetInts, чтобы вернуть IList, все в порядке выход:

 System.Collections.Generic.List`1[System.Int32]

И это возвращает false:

namespace NS {
    class Program {
        static IEnumerable<int> GetInts() {
            yield return 1;
        }
        static void Main() {
            var i = GetInts();
            var type = i.GetType();
            Console.WriteLine(type.Equals(typeof(IEnumerable<int>)));
        }
    }
}

Ответ 1

Если вы имеете в виду коллекцию, то просто as:

var asEnumerable = i as IEnumerable<int>;
if(asEnumerable != null) { ... }

Однако я предполагаю (из примера), что у вас есть Type:

Объект никогда не будет "из" типа IEnumerable<int> - но он может его реализовать; Я бы ожидал, что:

if(typeof(IEnumerable<int>).IsAssignableFrom(type)) {...}

. Если вы не знаете T (int в приведенном выше), проверьте все реализованные интерфейсы:

static Type GetEnumerableType(Type type) {
    foreach (Type intType in type.GetInterfaces()) {
        if (intType.IsGenericType
            && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
            return intType.GetGenericArguments()[0];
        }
    }
    return null;
}

и вызовите:

Type t = GetEnumerableType(type);

если это значение равно null, это не IEnumerable<T> для любого T - в противном случае проверьте T.

Ответ 2

Тот же метод, что и у Marc, но Linqier:

namespace NS
{
    class Program
    {
        static IEnumerable<int> GetInts()
        {
            yield return 1;
        }

        static void Main()
        {
            var i = GetInts();
            var type = i.GetType();
            var isEnumerableOfT = type.GetInterfaces()
                .Any(ti => ti.IsGenericType
                     && ti.GetGenericTypeDefinition() == typeof(IEnumerable<>));
            Console.WriteLine(isEnumerableOfT);
        }
    }
}

Ответ 3

Так как IEnumerable <T> наследовать IEnumerable (не общий), и если вам не нужно знать, когда тип просто IEnumerable, а не IEnumerable <T> то вы можете использовать:

        if (typeof(IEnumerable).IsAssignableFrom(srcType))

Ответ 4

Как определить, имеет ли объект тип IEnumerable <T> ?

Пожалуйста, не стесняйтесь использовать этот прекрасный, сверхмалый универсальный метод расширения, чтобы определить, реализует ли какой-либо объект IEnumerable интерфейс. Он расширяет тип Object, поэтому вы можете выполнить его с помощью любого экземпляра любого объекта, который вы используете.

public static class CollectionTestClass
{
    public static Boolean IsEnumerable<T>(this Object testedObject)
    {
        return (testedObject is IEnumerable<T>);
    }
}

Ответ 5

i имеет тип NS.1.Program+<GetInts>d__0, который является подтипом IEnumerable<int>. Таким образом, вы можете использовать

if (i is IEnumerable<int>) { ... }

или IsAssignableFrom (как в ответе Марка).

Ответ 6

Вы можете использовать ключевое слово is.

[TestFixture]
class Program
{
    static IEnumerable<int> GetInts()
    {
        yield return 1;
    }

    [Test]
    static void Maasd()
    {
        var i = GetInts();
        Assert.IsTrue(i is IEnumerable<int>);
    }
}