2010-12-12 49 views
21

Tôi đang có một thời gian khó hiểu khi sử dụng Object (boxing/unboxing) vs khi sử dụng Generics.C#: System.Object vs Generics

Ví dụ:

public class Stack 
{ 
    int position; 
    object[] data = new object[10]; 
    public void Push (object o) { data[position++] = o; } 
    public object Pop() { return data[--position]; } 
} 

VS.

public class Stack<T> 
{ 
    int position; 
    T[] data = new T[100]; 
    public void Push(T obj) {data[position++] = obj; } 
    public T Pop() { return data[--position]; } 
} 

Tôi nên sử dụng điều kiện nào và trong điều kiện nào? Nó có vẻ như với cách System.Object tôi có thể có các đối tượng của tất cả các loại hiện đang sống trong ngăn xếp của tôi. Vì vậy, điều này sẽ không luôn luôn thích hợp hơn? Cảm ơn!

+30

Điểm của việc thêm Mèo vào bộ sưu tập Chó là gì? Loại linh hoạt này chỉ tạo ra những con mèo chết. –

+0

Xem câu hỏi liên quan này quá [tại sao-không-luôn-sử dụng-generics] (http://stackoverflow.com/questions/4040746/why-not-always-use-generics) – nawfal

Trả lời

21

Luôn luôn sử dụng Generics! Sử dụng các kết quả của đối tượng trong các hoạt động cast và boxing/unboxing của các kiểu giá trị. Bởi vì những lý do này generics nhanh hơn và thanh lịch hơn (không đúc). Và - lý do chính - bạn sẽ không nhận được InvalidCastException s sử dụng Generics.

Vì vậy, generics nhanh hơn và lỗi có thể nhìn thấy tại thời gian biên dịch. System.Object có nghĩa là ngoại lệ thời gian chạy và truyền mà kết quả chung trong hiệu suất thấp hơn (đôi khi thấp hơn).

+1

Trừ khi bạn cần nhiều loại. Hãy thử làm đối tượng ASP.NET Session với Generics. –

+0

Có thể giống như Danh sách ? :) –

+1

Tôi có nghĩa là Generics có thể được sử dụng mọi lúc, nếu bạn thực sự cần nhiều loại được lưu trữ trong bộ sưu tập của mình, bạn có thể chỉ cần sử dụng một cái gì đó như List

6

Bạn sẽ gần như luôn muốn sử dụng Generics.

Việc áp dụng System.Object như một 'loại chung' được sử dụng:

  • ở cũ, các ứng dụng pre-FX2, vì Generics là không có sẵn.
  • khi bạn cần kết hợp các loại khác nhau, như trong các đối tượng Phiên ASP.NET và Ứng dụng.

Lưu ý rằng trong bạn mẫu đầu tiên (không chung chung) việc sử dụng trông giống như:

Stack s = ...; 
s.Push("Hello"); 
s.Push(1.23); 

double d = (double) s.Pop(); 
string t = (string) s.Pop(); 

Bạn thực sự muốn tránh tất cả typecasting này (để có thể đọc, an toàn và hiệu suất).

+2

Ngay cả khi trộn các loại, sử dụng một bộ sưu tập chung trong đó T xảy ra là 'đối tượng 'khiến bạn khá giống nhau. Nó không cải thiện loại an toàn nhưng nó không làm cho nó tồi tệ hơn. Nó cũng có nghĩa là bạn có thể sử dụng các phương thức LINQ trực tiếp mà không cần phải gọi phương thức mở rộng 'IEnumerable.Cast ()' – Davy8

1

Sử dụng Generics khi bạn muốn cấu trúc của mình xử lý một loại duy nhất. Ví dụ, nếu bạn muốn có một bộ sưu tập các chuỗi bạn muốn nhanh chóng một danh sách gõ mạnh của chuỗi như vậy:

List<string> myStrings = new List<string>(); 

Nếu bạn muốn nó để xử lý nhiều loại bạn có thể làm mà không Generics nhưng bạn sẽ phải chịu một nhỏ hiệu suất hit cho các hoạt động boxing/unboxing.

+0

"Loại đơn" hơi gây nhầm lẫn vì loại tĩnh có thể là loại cơ sở cho một số loại ... – SoftMemes

2

Với loại object, như bạn nói bạn cần phải thực hiện quyền anh và unboxing, điều này rất tẻ nhạt. Với generics, không cần thiết cho điều đó.

Ngoài ra, tôi muốn cụ thể hơn là loại của các đối tượng mà một lớp học có thể làm việc với và generics cung cấp cơ sở tuyệt vời cho điều đó. Tại sao kết hợp các loại dữ liệu không liên quan ở nơi đầu tiên? Ví dụ cụ thể của bạn về ngăn xếp nhấn mạnh lợi ích của generics trên loại dữ liệu cơ bản object.

// This stack should only contain integers and not strings or floats or bools 
Stack<int> intStack = new Stack<int>(); 
intStack.Push(1); 

Hãy nhớ rằng với generics bạn có thể chỉ định giao diện để lớp của bạn có thể tương tác với các đối tượng của nhiều lớp khác nhau, miễn là chúng đều triển khai cùng một giao diện.

4

Mặc dù có những lúc bạn muốn sử dụng bộ sưu tập không chung chung (ví dụ như bộ nhớ đệm), bạn hầu như luôn có bộ sưu tập các đối tượng đồng nhất không phải là các đối tượng không đồng nhất. Đối với một bộ sưu tập đồng nhất, ngay cả khi nó là một tập hợp các biến thể của loại cơ sở hoặc giao diện, nó luôn luôn tốt hơn để sử dụng Generics. Thao tác này sẽ giúp bạn không phải truyền kết quả dưới dạng loại thực trước khi bạn có thể sử dụng. Sử dụng generics làm cho mã của bạn hiệu quả hơn và dễ đọc hơn bởi vì bạn có thể bỏ qua mã để thực hiện việc truyền.

2

Generics luôn được ưu tiên nếu có thể.

Ngoài hiệu suất, Generics cho phép bạn đảm bảo về các loại đối tượng mà bạn đang làm việc.

Lý do chính nên chọn là trình biên dịch biết loại đối tượng là gì và có thể cung cấp cho bạn lỗi biên dịch mà bạn tìm thấy ngay lập tức thay vì lỗi thời gian chạy. 't kiểm tra.

1

Tất cả phụ thuộc vào những gì bạn cần trong thời gian dài.

Không giống như hầu hết các câu trả lời ở đây, tôi sẽ không nói "luôn sử dụng Generics" vì đôi khi bạn cần phải trộn mèo với dưa chuột.

Bằng mọi cách, hãy cố gắng dùng các thuốc generic cho tất cả các lý do đã đưa ra trong các câu trả lời khác, ví dụ nếu bạn cần kết hợp mèo và chó tạo lớp cơ sở Động vật có vú và có Stack<Mamal>.

Nhưng khi bạn thực sự cần hỗ trợ mọi loại có thể, đừng ngại sử dụng các đối tượng, chúng không bị cắn trừ khi bạn đang ngược đãi chúng. :)

7

Rất nhiều người đã đề xuất sử dụng Generics, nhưng có vẻ như tất cả họ đều bỏ lỡ điểm. Nó thường không phải về hiệu suất hit liên quan đến boxing nguyên thủy các loại hoặc đúc, đó là về việc trình biên dịch để làm việc cho bạn.

Nếu tôi có danh sách các chuỗi, tôi muốn trình biên dịch chứng minh với tôi rằng nó sẽ luôn chứa danh sách các chuỗi. Generics làm điều đó - tôi chỉ định ý định, và trình biên dịch chứng minh nó cho tôi. Lý tưởng nhất, tôi thích một hệ thống kiểu phong phú hơn, nơi bạn có thể nói một loại (ngay cả khi nó là kiểu tham chiếu) không thể chứa giá trị null, nhưng C# không may hiện không cung cấp.