将IsAssignableFrom与'open'泛型类型一起使用

Tha*_*Guy 57 c# generics reflection types

使用反射,我试图找到从给定基类继承的类型集.花了很长时间才弄清楚简单的类型,但是当涉及到泛型时我很难过.

对于这段代码,第一个IsAssignableFrom返回true,但第二个返回false.然而,最后的任务编译得很好.

class class1 { }
class class2 : class1 { }
class generic1<T> { }
class generic2<T> : generic1<T> { }

class Program
{
    static void Main(string[] args)
    {
        Type c1 = typeof(class1);
        Type c2 = typeof(class2);
        Console.WriteLine("c1.IsAssignableFrom(c2): {0}", c1.IsAssignableFrom(c2));

        Type g1 = typeof(generic1<>);
        Type g2 = typeof(generic2<>);
        Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));

        generic1<class1> cc = new generic2<class1>();
    }
}
Run Code Online (Sandbox Code Playgroud)

那么如何在运行时确定一个泛型类型定义是否来自另一个?

Kon*_*lph 82

答案到另一个问题:

public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
    var interfaceTypes = givenType.GetInterfaces();

    foreach (var it in interfaceTypes)
    {
        if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
            return true;
    }

    if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
        return true;

    Type baseType = givenType.BaseType;
    if (baseType == null) return false;

    return IsAssignableToGenericType(baseType, genericType);
}
Run Code Online (Sandbox Code Playgroud)

(如果您喜欢这个答案,请提交链接的答案,因为代码不是我的.)

  • 在下面的例子中,这个方法可能是错误的:IsAssignableToGenericType(typeof(A <string>),typeof(A <>)); //返回false (2认同)
  • 基于此方法,我创建了一个不同的方法来获取用于基类型的泛型参数:https://gist.github.com/2936304 (2认同)
  • 请注意,这比实际需要的成本更高,因为它为每个基类型迭代一次接口列表,这是不必要的。 (2认同)

Jon*_*Jon 11

您发布的确切代码不会返回令人惊讶的结果.

这说"假":

Type g1 = typeof(generic1<>);
Type g2 = typeof(generic2<>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
Run Code Online (Sandbox Code Playgroud)

这说"真实":

Type g1 = typeof(generic1<class1>);
Type g2 = typeof(generic2<class1>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
Run Code Online (Sandbox Code Playgroud)

不同之处在于,开放泛型类型不能具有实例,因此一个不能"分配"给另一个实例.

来自文档:

返回trueif c和当前 Type表示相同类型,或者当前Type是否在继承层次结构中c,或者当前Typec实现的接口,或者if c是泛型类型参数,而current是否 Type代表其中一个约束c.false如果这些条件都不成立,或者如果cnull.

在这种情况下,显然这些条件都不属实.还有一个额外的说明:

泛型类型定义不能从闭合构造类型中分配.也就是说,您不能将闭合的构造类型MyGenericList<int>(MyGenericList(Of Integer)在Visual Basic中)分配给类型 的变量MyGenericList<T>.

  • 很好的解释! (2认同)