当我们有这样的事情时:
interface ISomething<U,V> { ... } class Something<U,V> : ISomething<U,V> { ... }
typeof(ISomething<,>)和typeof(Something<,>)将产生“通用类型定义”.但是如果我们将接口类型作为类实现的接口,它将是一个构造类型,它的类型参数都没有实际绑定:
typeof(Something<,>).GetInterfaces().SingleOrDefault()
MSDN特别提到了这一点.我想要的是构建相同类型(构造类型)的ISomething<,>直接(没有子类,他们寻找基本类型),我找不到任何方法这样做.
附加信息:
我甚至试过这个:
Type t1 = typeof(ISomething<,>); Type t2 = t1.MakeGenericType(t1.GetGenericArguments()) // Yields a generic type definition Type t3 = typeof(Something<,>).GetInterfaces().SingleOrDefault();
在上面的代码中:
t1.Equals(t2)为真,但t1.Equals(t3)为假,显然是因为构造了t3.
令人惊讶的是,t1.GetGenericArguments()[0] .Equals(t3.GetGenericArguments()[0])是假的,虽然两者都是开放的(IsGenericParameter = true),我找不到它们的属性有任何区别.
这就是我需要这样做的原因:我需要一种在列表中存储Type对象的规范形式.对象有时来自基类/接口(例如上面的t3),有时直接来自(例如t1).我需要能够将这些相互比较.我无法存储泛型类型定义(使用.GetGenericTypeDefinition()),因为有时候我会有一个部分打开的构造泛型类型(比如ISomething),GetGenericTypeDefinition会给我一个没有指定任何类型参数的类型.
制作我认为可能有效的类型规范的唯一方法是检查所有类型参数是否未绑定,并执行GetGenericTypeDefinition.否则保持构造的类型.
解决方法
你让自己搞砸了.检查此程序的输出并确保您理解它.在这里,我已经对类型参数进行了alpha重命名,因此由于两个名为U的东西没有不明确的原因:
interface I<S,T> { I<S,T> M(); } class C<U,V> : I<U,V> { public I<U,V> M() {return null;} public C<U,V> N() {return null;} } public class MainClass { public static void Main() { var i1 = typeof(I<,>); var i2 = typeof(I<int,int>); var i3 = i2.GetGenericTypeDefinition(); var i4 = i1.GetMethod("M").ReturnType; var c1 = typeof(C<,>); var c2 = typeof(C<int,int>); var c3 = c2.GetGenericTypeDefinition(); var c4 = c1.GetMethod("N").ReturnType; var i5 = c1.GetMethod("M").ReturnType; var i6 = c1.GetInterfaces()[0]; System.Console.WriteLine(i1 == i2); // false -- I<,> is not I<int,int> System.Console.WriteLine(i1 == i3); // true -- I<int,int>'s decl is I<,> System.Console.WriteLine(i1 == i4); // true -- I<,> is I<S,T> System.Console.WriteLine(i1 == i5); // false -- I<S,T> is not I<U,V> System.Console.WriteLine(i1 == i6); // false -- I<S,V> System.Console.WriteLine(c1 == c2); // false -- C<,> is not C<int,int> System.Console.WriteLine(c1 == c3); // true -- C<int,int>'s decl is C<,> System.Console.WriteLine(c1 == c4); // true -- C<,> is C<U,V> } }