Когда у нас есть что-то вроде этого:
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.В противном случае сохраните созданный тип.