如何判断Type是否实现IList <>?

Joe*_*ite 16 .net generics reflection

我想编写一个方法,使用Reflection来判断给定的Type是否实现IList<T>.例如:

IsGenericList(typeof(int))                       // should return false
IsGenericList(typeof(ArrayList))                 // should return false
IsGenericList(typeof(IList<int>))                // should return true
IsGenericList(typeof(List<int>))                 // should return true
IsGenericList(typeof(ObservableCollection<int>)) // should return true
Run Code Online (Sandbox Code Playgroud)

在我的用法中,我可以假设类型将始终是实例化的泛型类型(或者根本不是通用的类型).

不幸的是,这并不像它应该的那么容易.明显的解决方案:

public bool IsGenericList(Type type)
{
    return typeof(IList<>).IsAssignableFrom(type);
}
Run Code Online (Sandbox Code Playgroud)

不起作用; 它总是返回false.显然,非实例化的泛型类型IList<>不会像我期望的那样实现IsAssignable:IList<>不能从中分配List<T>.

我也试过这个:

public bool IsGenericList(Type type)
{
    if (!type.IsGenericType)
        return false;
    var genericTypeDefinition = type.GetGenericTypeDefinition();
    return typeof(List<>).IsAssignableFrom(genericTypeDefinition);
}
Run Code Online (Sandbox Code Playgroud)

即,type转换为非实例化的泛型,如IList<int>- > IList<>,然后再次尝试IsAssignableFrom.当类型是一个实例化将返回true IList<T>,如IList<int>,IList<object>等,但它返回实现类错误IList<T>,如List<int>,ObservableCollection<double>等,这样显然IList<>是不分配List<>.再一次,不是我所期望的.

我如何编写IsGenericList并使其工作如上例所示?

Luc*_*ero 26

实际上,您不能拥有泛型类型定义的实例.因此,IsAssignableFrom()方法按预期工作.要实现您的目标,请执行以下操作:

public bool IsGenericList(Type type)
{
    if (type == null) {
        throw new ArgumentNullException("type");
    }
    foreach (Type @interface in type.GetInterfaces()) {
        if (@interface.IsGenericType) {
            if (@interface.GetGenericTypeDefinition() == typeof(ICollection<>)) {
                // if needed, you can also return the type used as generic argument
                return true;
            }
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

出于好奇,你需要做什么?


Col*_*nic 15

我也想测试一个类型是否IList<T>为某些T 实现了.我对Lucero的答案做了明显的改变,但它引起了原始答案中不存在的微妙错误.这是我的最终编辑:

    /// <summary>
    /// Test if a type derives from IList of T, for any T.
    /// </summary>
    public bool TestIfGenericList(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }

        var interfaceTest = new Predicate<Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));

        return interfaceTest(type) || type.GetInterfaces().Any(i => interfaceTest(i));
    }
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这确实比接受的答案更好,因为它适用于`IList <T>`本身. (3认同)