Недавно я столкнулся с интересным поведением наследования типа C# generic. Представьте себе следующий пример:Дополнительный тип в наследовании открытых общих типов в C#
class Foo<T> {}
class Bar<T> : Foo<T> {}
Когда мы используем замкнутые родовые типы, их поведение с точки зрения наследования является довольно очевидно:
Console.WriteLine(typeof(Bar<int>).BaseType == typeof(Foo<int>)); // True
Но когда мы используем открытые универсальные типы, мы получаем следующее:
Console.WriteLine(typeof(Bar<>).BaseType == typeof(Foo<>)); // False
Лично я ожидал, что эта строка будет распечатана True
. Итак, давайте посмотрим на базовый тип Bar<>
:
Action<Type> discoverType = type =>
{
Console.WriteLine("Type name: " + type.ToString());
Console.WriteLine("Is generic type definition: " +
type.IsGenericTypeDefinition);
Console.WriteLine("Generic ags: " +
string.Join<Type>(", ", type.GetGenericArguments()));
Console.WriteLine("Types in generic:" +
string.Join<Type>(", ", type.GenericTypeArguments));
Console.WriteLine(Environment.NewLine);
};
Type baseType = typeof(Bar<>).BaseType;
discoverType(baseType);
Type openType = baseType.GetGenericTypeDefinition();
discoverType(openType);
Линии выше производить следующий вывод:
Type name: GenericsReflection.Program+Foo`1[T]
Is generic type definition: False
Generic ags: T
Types in generic:T
Type name: GenericsReflection.Program+Foo`1[T]
Is generic type definition: True
Generic ags: T
Types in generic:
Так вот у нас есть тип (первый), который был создан из Foo<T>
(второй), заменив T
на T
(необычный, но действительный, так как T
также является созданным во время выполнения). Если у нас есть еще один тип, который наследуется от Foo<T>
, то новый базовый тип будет сгенерирован:
class Another<T> : Foo<T> { }
Console.WriteLine(typeof(Another<>).BaseType == typeof(Bar<>).BaseType); // False
Итак, мой вопрос: зачем нам эти «прокси» типы между Bar<>
и Foo<>
и между Another<>
и Foo<>
, почему открытые общие типы не могут быть унаследованы друг от друга?
Джон, спасибо за объяснение, теперь у меня это есть. Я просто ожидал, что базовый класс универсального определения 'X2',' X3', 'X4' будет' Foo <> '. Но теперь мне кажется, что этот базовый класс должен передавать аргументы типа из 'Bar' в 'Foo '. –
takemyoxygen