2013-08-22 131 views
2

最近我遇到了C#泛型類型繼承的一個有趣的行爲。想象一下下面的例子:在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<>:這是從創建

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: 

所以在這裏我們有一個類型(第一個):上述

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); 

的線條產生下面的輸出Foo<T>(第二個)替換TT(不尋常,但有效,因爲T也是運行時生成類型)。如果我們有另一種類型,從Foo<T>繼承,那麼新的基本類型,將產生:

class Another<T> : Foo<T> { } 

Console.WriteLine(typeof(Another<>).BaseType == typeof(Bar<>).BaseType); // False 

所以,我的問題是:爲什麼我們需要Bar<>Foo<>之間和Another<>Foo<>之間的這些「代理」類型,爲什麼開放的泛型類型不能彼此繼承?

回答

3

例如,如果您給出兩個類型參數的不同名稱(例如T1T2),則會更清楚。那麼,這種差異變得更加清晰:

Type name: Foo`1[T2] 
Is generic type definition: False 
Generic ags: T2 
Types in generic:T2 


Type name: Foo`1[T1] 
Is generic type definition: True 
Generic ags: T1 
Types in generic: 

他們真的是不同的 - typeof(Bar<>).BaseType已經Bar<>鍵入指定*參數) - 它只是你需要Bar<>本身有是具體你會得到一個具體的Foo<>之前。換句話說,typeof(Bar<>).BaseType構造的類型,而typeof(Foo<>)不是。有關詳細信息,請參閱Type.IsConstructedGenericType(這是另一個將爲這兩種類型提供不同值的屬性)。

換一種方式,可以考慮這三個聲明:

class X1 : Foo<string> {} 
class X2<T> : Foo<string> {} 
class X3<TKey, TValue> : Foo<TKey> {} 
class X4<TKey, TValue> : Foo<TValue> {} 

你會希望每個這些類型的基本類型是一樣的typeof(Foo<>)?在第一種情況和第二種情況下,它肯定是Foo<string>而不是Foo<> ...那麼爲什麼你會期望它不同,只是因爲它使用類型參數而不是具體類型?

+0

喬恩,謝謝你的解釋,現在我明白了。我只是期望'X2','X3','X4'的泛型定義的基類是'Foo <>'。但是現在看來很清楚,這個基類需要將類型參數從'Bar '傳遞到'Foo '。 – takemyoxygen