GetGenericTypeDefinition возвращает false при поиске IEnumerable <T>в списке <T> - PullRequest
4 голосов
/ 15 декабря 2009

После этот вопрос , почему enumerable в этом:

Type type = typeof(List<string>);
bool enumerable = (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>));

возврат false?


Редактировать 1

Поскольку вышеприведенное не работает, как лучше всего определить, реализует ли класс IEnumerable?

Ответы [ 4 ]

8 голосов
/ 15 декабря 2009

Здесь я мог бы использовать GetListType(type) и проверить null:

static Type GetListType(Type type) {
    foreach (Type intType in type.GetInterfaces()) {
        if (intType.IsGenericType
            && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) {
            return intType.GetGenericArguments()[0];
        }
    }
    return null;
}
4 голосов
/ 15 декабря 2009

Потому что

(typeof(List<String>)).GetGenericTypeDefinition()

возвращается

typeof(List<>)

GetGenericTypeDefinition может возвращать только один тип, но не все несвязанные типы, реализованные целевым экземпляром Type.

Чтобы определить, реализует ли X<T> IY<T> либо

  • Reify T (т.е. сделать его реальным типом) и проверить с конкретными типами. То есть X<string> реализует IY<string>. Это можно сделать с помощью отражения или с помощью оператора as.

  • Type.GetInterafces() (или Type.GetInterface(t)).

Второй будет легче. Тем более, что это также дает ложь:

Type t = typeof(List<string>).GetGenericTypeDefinition();
bool isAssign = typeof(IEnumerable<>).IsAssignableFrom(t);
2 голосов
/ 15 декабря 2009

Если вам нужен быстрый тест для определенных закрытых универсальных типов - например, чтобы проверить, реализует ли List<string> IEnumerable<string> - тогда вы можете сделать что-то вроде этого:

Type test = typeof(List<string>);
bool isEnumerable = typeof(IEnumerable<string>).IsAssignableFrom(test);

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

Type test = typeof(List<string>);
bool isEnumerable = test.GetInterfaces().Any(i =>
    i.IsGenericType && (i.GetGenericTypeDefinition() == typeof(IEnumerable<>)));
1 голос
/ 15 декабря 2009

Следующее возвращает true и является своего рода точкой, проверяющей интерфейсы:

 enumerable = typeof(List<string>).GetInterfaces()
               .Contains(typeof(IEnumerable<string>));
...