Определите, имеет ли коллекция тип IEnumerable <T> - PullRequest
50 голосов
/ 04 декабря 2009

Как определить, относится ли объект к типу IEnumerable ?

Код:

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]

И это возвращает ложь:

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

Ответы [ 7 ]

100 голосов
/ 04 декабря 2009

Если вы имеете в виду коллекцию , то просто 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);

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

14 голосов
/ 11 апреля 2016

Поскольку IEnumerable наследует IEnumerable (не является универсальным), и если вам не нужно знать, когда тип просто IEnumerable, а не IEnumerable , тогда вы можете использовать:

if (typeof(IEnumerable).IsAssignableFrom(srcType))
14 голосов
/ 04 декабря 2009

Та же техника, что и у ответа Марка, но Линкьер:

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);
        }
    }
}
7 голосов
/ 04 декабря 2009

Как определить, относится ли объект к типу IEnumerable ?

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

public static class CollectionTestClass
{
    public static Boolean IsEnumerable<T>(this Object testedObject)
    {
        return (testedObject is IEnumerable<T>);
    }
}
3 голосов
/ 04 декабря 2009

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

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

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

1 голос
/ 04 декабря 2009

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

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

    [Test]
    static void Maasd()
    {
        var i = GetInts();
        Assert.IsTrue(i is IEnumerable<int>);
    }
}
0 голосов
/ 04 декабря 2009
...