2010-01-31 5 views
100

tôi đang trải qua Asp.Net MVC lesson và biết được rằng, đối với một phương pháp để đủ điều kiện như một hành động cho một bộ điều khiển,Chính xác thì "loại generic mở" trong .NET là gì?

  • Nó không phải có một "mở loại generic"

Tôi hiểu Generics phần nào và sử dụng chúng ở một mức độ nào đó, nhưng:

  • loại mở chung trong .Net là gì.
  • Có một thứ như loại chung đóng không?
  • Mở loại chung là thuật ngữ không được sử dụng thường xuyên. Những gì được sử dụng/nhầm lẫn với nó?

Trả lời

168

C# ngôn ngữ định nghĩa một kiểu mở là một loại đó là hoặc là một đối số kiểu hoặc một kiểu generic định nghĩa với lập luận kiểu không rõ:

Tất cả các loại có thể được phân loại là một trong hai loại mở hoặc các loại khép kín . An kiểu mở là loại liên quan đến thông số loại. Cụ thể hơn:

  • Thông số loại xác định loại mở.
  • Loại mảng là loại mở nếu và chỉ khi loại phần tử của nó là loại mở.
  • A loại được xây dựng là loại mở nếu và chỉ khi một hoặc nhiều đối số loại của nó là loại mở. A kiểu lồng nhau được xây dựng là một loại mở nếu và chỉ khi một hoặc nhiều đối số kiểu của nó hoặc đối số kiểu của loại chứa (s) là loại mở.

A loại đóng là loại không phải là loại mở.

Do đó T, List<T>, và Dictionary<string,T>, và Dictionary<T,U> là tất cả các loại mở (TU những luận cứ loại) trong khi các loại List<int>Dictionary<string,int> are closed.

Có một khái niệm liên quan: An loại chung chung không liên kết là loại chung với các đối số kiểu không xác định. Không thể sử dụng loại không liên kết trong các biểu thức khác ngoài typeof() và bạn không thể khởi tạo hoặc gọi phương thức của nó. Ví dụ: List<>Dictionary<,> là các loại không liên kết.

Để làm rõ sự khác biệt tinh tế giữa một kiểu mở và một loại không ràng buộc:

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

Nếu bạn chạy đoạn này, nó sẽ in ra

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

đó là tên CLR cho List<int> . Rõ ràng khi chạy là đối số kiểu là System.Int32. Điều này làm cho List<T> a bị ràng buộc loại mở.

Khi chạy, bạn có thể sử dụng phản ánh để ràng buộc đối số kiểu để các tham số kiểu không xác định các kiểu generic không ràng buộc với 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."); 

Bạn có thể kiểm tra xem một loại là một loại generic không ràng buộc (chung kiểu định nghĩa) mà từ đó bạn có thể xây dựng các loại ràng buộc với Type.IsGenericTypeDefinition property:

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

Để có được kiểu cởi ra từ một loại xây dựng trong thời gian chạy, bạn có thể sử dụng số Type.GetGenericTypeDefinition method.

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

Lưu ý rằng đối với loại chung, bạn có thể có định nghĩa loại hoàn toàn không bị ràng buộc hoặc định nghĩa hoàn toàn bị ràng buộc. Bạn không thể ràng buộc một số thông số loại và để người khác không bị ràng buộc. Ví dụ: bạn không thể có Dictionary<int,> hoặc Dictionary<,string>.

+8

+1 thông tin tuyệt vời - Tôi đã học được điều gì đó mới mẻ hôm nay. Tôi biết rằng Danh sách <> là một loại chung chung, nhưng bây giờ tôi biết thuật ngữ kỹ thuật chính xác. – IAbstract

+2

Bạn * có thể * thực sự đóng một phần loại chung bằng cách cung cấp một đối số kiểu tự nó là một kiểu chung mở. Tuy nhiên, đây là một kết thúc chết. Khung không chính thức nhận ra trạng thái một phần này, coi nó là không đóng và cũng không mở, và do đó nó không cho phép bạn làm bất cứ điều gì hữu ích với nó. –

+1

giải thích tuyệt vời về sự khác biệt giữa loại mở và loại không liên kết - không biết trước! – nawfal

5

"Loại chung mở" chỉ là loại chung mà chưa được chỉ định loại (ví dụ: CargoCrate<T>). Nó trở thành "đóng cửa" khi một loại bê tông đã được chỉ định (ví dụ: CargoCrate<Widget>).

Ví dụ, nói rằng bạn có một cái gì đó như thế này:

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> { 
} 

Ở đây, loại picnicBasket 's mở cửa: không có gì ấy chưa được giao cho T. Khi bạn thực hiện một PicnicBlanket cụ thể với một loại cụ thể - ví dụ, bằng cách viết PicnicBlanket<Food> p = new PicnicBlanket<Food>() - bây giờ chúng tôi gọi nó là đóng.

8

Chỉ cần thêm:

Dictionary<string, T> (hay chính xác hơn Dictionary<string,>) vẫn là một kiểu mở.

Ví dụ:

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

@Mehrdad Afshari: Xin lỗi, nhưng bạn vẫn có thể nhận được những gì bạn gọi là bán loại đóng ... – leppie

+0

Ngoài ra, tôi không có ý tưởng làm thế nào để xây dựng (hoặc đại diện cho loại), có thể là một câu hỏi đáng giá. – leppie

+0

@Mehrdad Afshari: trông khá cởi mở đối với tôi, nhưng tôi cũng mở để gợi ý. :) – leppie

4

Có ba loại định dạng generic. Để làm cho nó ngắn, trong này tuyên bố (giản thể):

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> 
  • Dictionary<TKey, TValue> là một vô biên generic loại.

  • KeyValuePair<TKey, TValue> là, trong trường hợp này, loại chung được xây dựng mở.Nó có một số tham số kiểu, nhưng chúng đã được định nghĩa ở nơi khác (trong Từ điển, trong trường hợp này).

  • Dictionary<string, int> sẽ là loại chung đóng được xây dựng.