2010-01-31 157 views
100

我正在經歷Asp.Net MVC lesson並瞭解到,對於一個方法有資格作爲控制器的動作,.NET中的「open generic type」究竟是什麼?

  • 它不能有「開放式泛型類型」

我明白仿製藥有些並利用它們在一定程度上,但:

  • 什麼是.NET中開放式泛型類型
  • 是否有這樣的事情作爲封閉泛型類型
  • Open generic type是一個不經常使用的術語。什麼使用/與它混淆?

回答

168

C#語言定義的開放式是一種類型的這兩種類型參數或未知類型的參數定義的泛型類型:

所有類型都可歸類爲開放類型或封閉類型。 開放式是一種涉及類型參數的類型。更具體地說:

  • 類型參數定義了一個開放類型。
  • 當且僅當其元素類型爲開放類型時,數組類型纔是開放類型。
  • A 構造類型當且僅當其一個或多個類型參數是開放類型是一個開放類型。 A 構造的嵌套類型當且僅當其一個或多個類型參數或其包含類型的類型參數是開放類型時是開放類型。

A 封閉式是一種非開放式的類型。

因此TList<T>,和Dictionary<string,T>,和Dictionary<T,U>都是開放類型(TU是類型參數),而List<int>Dictionary<string,int>閉合的類型。

有一個相關概念:一個未綁定的泛型類型是一個帶有未指定類型參數的泛型類型。非綁定類型不能用於除typeof()以外的表達式,並且您不能實例化或調用其方法。例如,List<>Dictionary<,>是未綁定類型。

要澄清一個開放型和未綁定類型之間的微妙的區別:

class Program { 
    static void Main() { Test<int>(); } 
    static void Test<T>() { 
     Console.WriteLine(typeof(List<T>)); // Print out the type name 
    } 
} 

如果你運行這段代碼,它會打印出

System.Collections.Generic.List`1[System.Int32] 

這是List<int>的CLR名稱。在運行時很明顯,類型參數是System.Int32。這使得List<T>一個約束開放類型。

在運行時,你可以使用反射來綁定類型參數的未綁定的泛型類型的未指定類型參數與Type.MakeGenericType method

Type unboundGenericList = typeof(List<>); 
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int)); 
if (listOfInt == typeof(List<int>)) 
    Console.WriteLine("Constructed a List<int> type."); 

可以檢查類型是否是綁定的泛型類型(泛型類型定義),從中可以構造綁定類型與Type.IsGenericTypeDefinition property

Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True 
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False 

爲了獲得在運行時構造類型的未綁定類型,可以使用Type.GetGenericTypeDefinition method

Type listOfInt = typeof(List<int>); 
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>) 

請注意,對於泛型類型,您可以具有完全未綁定的類型定義或完全綁定的定義。您無法綁定某些類型參數,也不能將其他人綁定。例如,您不能有Dictionary<int,>Dictionary<,string>

+8

+1條信息 - 今天我學到了一些新東西。我知道List <>是一個泛型類型,但現在我知道正確的技術術語。 – IAbstract 2010-01-31 20:34:30

+2

您* *實際上可以通過提供一個本身爲開放泛型類型的類型參數來部分關閉泛型類型。但是,這是一個死路一條。該框架沒有正式承認這種局部狀態,認爲它既不封閉也不公開,因此它不允許你做任何有用的事情。 – 2010-03-16 21:34:52

+1

關於開放式和非結合式之間的區別的很好的解釋 - 以前不知道! – nawfal 2013-05-14 05:08:04

5

「開放泛型類型」只是一個尚未指定類型的泛型類型(例如,CargoCrate<T>)。一旦具體類型被分配,它就變成「關閉」(例如CargoCrate<Widget>)。

例如,假設你有這樣的事情:

public class Basket<T> { 
    T[] basketItems; 
} 

public class PicnicBlanket<T> { 
    Basket<T> picnicBasket; // Open type here. We don't know what T is. 
} 

           // Closed type here: T is Food. 
public class ParkPicnicBlanket : PicnicBlanket<Food> { 
} 

這裏,picnicBasket的類型是開放的:什麼也沒有尚未分配到T。當您製作具體類型的具體PicnicBlanket時 - 例如,通過編寫PicnicBlanket<Food> p = new PicnicBlanket<Food>() - 我們現在稱其爲已關閉

8

我想補充:

Dictionary<string, T>(或者更準確地說Dictionary<string,>)仍然是一個開放型。

例子:

void Foo<T>(Dictionary<string,T> dic) { ... } 
+0

@Mehrdad Afshari:對不起,但你仍然可以得到你所說的半封閉類型... – leppie 2010-01-31 21:08:28

+0

另外,我不知道如何構建(或代表類型),可能是一個有價值的問題。 – leppie 2010-01-31 21:11:48

+0

@Mehrdad Afshari:對我來說看起來很開放,但我也樂於接受建議。 :) – leppie 2010-01-31 21:16:07

4

有三種通用類型。要長話短說,在此(簡化)聲明:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> 
  • Dictionary<TKey, TValue>無限泛型類型

  • KeyValuePair<TKey, TValue>在這種情況下是開放構建的通用類型。它有一些類型參數,但它們已經在其他地方定義了(在本例中是在Dictionary中)。

  • Dictionary<string, int>將是封閉構建的通用類型