开发者

How to create a constructed generic type without specifying any type parameters

When we have something like开发者_如何学Go this:

interface ISomething<U,V> { ... }
class Something<U,V> : ISomething<U,V> { ... }

typeof(ISomething<,>) and typeof(Something<,>) will result in a "Generic type definition". But if we get to the interface type as the interface implemented by the class, it will be a constructed type, that none of its type parameters are actually bound:

typeof(Something<,>).GetInterfaces().SingleOrDefault()

MSDN specifically mentions this. What I want, is to construct the same type (constructed type) of ISomething<,> directly (without sub-classing and them looking for the base type), and I could not find any way to do so.

Additional info:

I even tried this:

Type t1 = typeof(ISomething<,>);
Type t2 = t1.MakeGenericType(t1.GetGenericArguments()) // Yields a generic type definition

Type t3 = typeof(Something<,>).GetInterfaces().SingleOrDefault();

In the above code:

t1.Equals(t2) is true, but t1.Equals(t3) is false, obviously because t3 is constructed.

Surprisingly, t1.GetGenericArguments()[0].Equals(t3.GetGenericArguments()[0]) is false, although both are open (IsGenericParameter = true), and I couldn't find any difference in their properties.

And here's why I need to do this: I need a canonical form of storing Type objects in a list. The objects sometimes come from base classes / interfaces (such as t3 above) and sometimes directly (such as t1). I will need to be able to compare these to each other. I can't store the generic type definition (using .GetGenericTypeDefinition()) because sometimes I will have a partially open constructed generic type (like ISomething), and GetGenericTypeDefinition will give me a type without any type arguments specified.

The only way for making the types canonical that I've thought might work, is to check if all of the type arguments are unbound, and do a GetGenericTypeDefinition. Otherwise keep the constructed type.


You are getting yourself all messed up here. Examine the output of this program and make sure that you understand it. Here I've alpha-renamed the type parameters so that there is no unclarity due to two things both named 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, T> is not I<U, 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>
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜