是不是可以从通用列表中分配的通用IList?

时间:2009-07-24 12:47:06

标签: c# .net generics collections

bool IsTypeAGenericList(Type listType)
{
  typeof(IList<>).IsAssignableFrom(listType.GetGenericTypeDefinition())
}
在给定typeof(List<int>)

返回false。

我认为这是因为两个类型参数可以不同,对吗?

4 个答案:

答案 0 :(得分:8)

实际上,这有效:

public static bool IsGenericList(Type type)
{
  if (!type.IsGenericType)
    return false;
  var genericArguments = type.GetGenericArguments();
  if (genericArguments.Length != 1)
    return false;

  var listType = typeof (IList<>).MakeGenericType(genericArguments);
  return listType.IsAssignableFrom(type);
}

答案 1 :(得分:3)

这与开放构造的类型有关。

当你说:

class List<T> : IList<T>

你实际上在说:我的类名为List,它有一个名为T的类型参数,它实现了从IList&lt;&gt;构造的接口。使用相同的T 。因此定义部分中的T和“implements”部分中的T都引用相同的类型参数 - 您在冒号之前声明它,然后在冒号后立即引用它。

令人困惑,因为IList<>的类型参数也称为T - 但这完全是一个不同的类型参数。所以让我们重新声明我们的具体类:

class List<U> : IList<U>

这完全等同于上面的内容,现在我们在引用List的类型参数时可以说“U”,而在引用IList中的类型时可以说是T.他们是不同的类型。

现在可以更容易地了解为什么泛型类型定义List<U>(当您说typeof(List<>)时的意思)没有实现generifc类型定义IList<T>(这是什么你的意思是当你说typeof(IList<>)),而是它实现了开放的通用构造类型IList<U>(也就是说,IList用List自己的类型的paremeter构造)。

基本上,泛型类型定义从不继承或实现其他泛型类型定义 - 它们通常使用自己的类型参数和其他泛型类型定义来实现开放构造类型。

Ripper234的答案显示了如何使用Reflection处理这个特殊情况,所以我不再重复;我只想澄清这些类型之间的关系,我希望它至少可以理解。

答案 2 :(得分:2)

我想这个方法没有意义,因为一个实例从不泛型类型 - 它总是用特定的类型参数构造。

换句话说,你永远不会有一个“open”变量来分配,也不能引用一个打开的实例作为赋值的值。

正如你所说,你不知道类型参数是否相同 - 所以(例如)你可以定义:

class BizarreList<T> : IList<int>

感觉应该有一些表达关系的方式......

答案 3 :(得分:1)

以下是AutoMapper的扩展方法:

    public static bool IsCollectionType(this Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ICollection<>))
        {
            return true;
        }

        IEnumerable<Type> genericInterfaces = type.GetInterfaces().Where(t => t.IsGenericType);
        IEnumerable<Type> baseDefinitions = genericInterfaces.Select(t => t.GetGenericTypeDefinition());

        var isCollectionType = baseDefinitions.Any(t => t == typeof(ICollection<>));

        return isCollectionType;
    }