Как создать составной универсальный тип без указания каких-либо параметров типа - PullRequest
7 голосов
/ 15 июля 2011

Когда у нас есть что-то вроде этого:

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), и я не смог найти никакой разницы в их свойствах.

И вот почему мне нужно сделать это: Мне нужна каноническая форма хранения объектов типа в списке.Объекты иногда приходят из базовых классов / интерфейсов (таких как t3 выше), а иногда и напрямую (таких как t1).Мне нужно будет сравнить их друг с другом.Я не могу сохранить определение универсального типа (используя .GetGenericTypeDefinition()), потому что иногда у меня будет частично открытый составной универсальный тип (например, ISomething), а GetGenericTypeDefinition даст мне тип без каких-либо заданных аргументов типа.

Единственный способ сделать канонические типы, которые, как я думал, могут работать, - это проверить, не связаны ли все аргументы типа, и выполнить GetGenericTypeDefinition.В противном случае сохраните созданный тип.

1 Ответ

6 голосов
/ 15 июля 2011

Вы запутались здесь.Изучите результаты этой программы и убедитесь, что вы ее понимаете.Здесь я переименовал параметры типа в альфа-формате, чтобы не было неясности из-за двух вещей, названных 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>
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...