将类型参数传递给没有约束的泛型类型会引发约束异常

时间:2015-11-04 19:19:11

标签: c# .net generics types

请考虑以下代码:

IEnumerable<Type> oneParameterTypes = Assembly.GetAssembly(typeof(object))
                                      .GetTypes()
                                      .Where(t => t.IsGenericType)
                                      .Where(t => t.GetGenericArguments().Length == 1)
                                      .Where(t => t.GetGenericArguments().Single().GetGenericParameterConstraints().Length == 0);

oneParameterTypes应该包含System.dll程序集中的所有泛型类型,这些类型可以传递一个泛型类型参数,并且不对其应用任何约束。

现在,让我们传入一个类型参数:

IEnumerable<Type> intParameterTypes = oneParameterTypes.Select(t => t.MakeGenericType(typeof(int)))
                                                       .ToList();

这应该有用,对吗?我的意思是,oneParameterTypes中的所有类型都没有类型约束,因此System.Int32应该是有效的类型。

然而,该行引发了以下异常:

  

GenericArguments [0],&#39; System.Int32&#39;,on&#39; System.RuntimeType + ListBuilder`1 [T]&#39;违反了&#39; T&#39;。

的约束

这个ListBuilder'1类型是什么?为什么它在oneParameterTypes中有类型约束?为什么我的Where过滤器无效?

3 个答案:

答案 0 :(得分:2)

我认为克里斯是正确的。

试试这样:

IEnumerable<Type> oneParameterTypes = Assembly.GetAssembly(typeof (object))
    .GetTypes()
    .Where(t => t.IsGenericType)
    .Where(t => t.GetGenericArguments().Length == 1)
    .Where(t => t.GetGenericArguments().Single().GetGenericParameterConstraints().Length == 0 &&
                !genericArgument.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint);
    });

答案 1 :(得分:1)

文档并不清楚Type.GetGenericParameterConstraints实际查找的内容:

  

使用IsClass属性确定约束是否是基类约束;如果属性返回false,则约束是接口约束。 如果类型参数没有类约束且没有接口约束,则返回空数组。

您可以隐含地理解它只会检查基类或接口约束。要全面了解存在约束的情况,您需要对GenericParameterAttributes进行额外检查。您可以使用HasFlag或按位掩码:

IEnumerable<Type> oneParameterTypes = Assembly.GetAssembly(typeof(object))
              .GetTypes()
              .Where(t => t.IsGenericType)
              .Where(t => t.GetGenericArguments().Length == 1)
              .Where(t => t.GetGenericArguments().Single().GetGenericParameterConstraints().Length == 0 && !t.GenericParameterAttributes.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint);

答案 2 :(得分:0)

typeof()或.GetType()方法不返回实际的类,而是返回Type Object表示,这将帮助我们将类型名称用作字符串。

相反,您可以使用反射类并查找该类型的类并将其用作参数

相关问题