Thứ Ba, 18 tháng 9, 2012

Tìm hiểu khái niệm Generics trong C#

Generics là gì?
Generics là một phần kiểu hệ thống của .NET Framework cho phép bạn định nghĩa một kiểu bỏ đi một số chi tiết không xác định. Thay vì xác định rõ các kiểu của các lớp tham số hay thành viên, bạn có thể cho phép mã lệnh sử dụng kiểu của bạn để chỉ định nó. Điều này cho phép mã lệnh sử dụng của bạn biến đổi thích ứng kiểu của bạn tới chỉ định cần thiết của chính nó.
Phiên bản 2.0 của .NET Framework chứa một số lớp generic khác nhau trong namespace có tên là System.Collections.Generic, bao gồm Dictionary, Queue, SortedDictionary, và SortedList. Các lớp này làm việc tương tự như đối với các phần tương ứng nongeneric của nó trong System.Collections, tuy nhiên chúng mang đến hiệu suất được cải thiện và tính an toàn kiểu.

Tại sao phải sử dụng Generics?
Phiên bản 1.0 và 1.1 của .NET Framework không hỗ trợ generics. Thay vào đó, lập trình viên sử dụng lớp Object với các tham số và thành viên sẽ phải chuyển đổi tới các lớp khác dựa trên lớp Object. Generics mang đến hai tính năng cải tiến đáng kể đối với việc sử dụng lớp Object :
Giảm bớt lỗi vận hành (Reduced run-time errors): Trình biên dịch không thể kiểm tra các lỗi kiểu dữ liệu khi bạn chuyển đổi qua đựa trên lớp Object . Ví dụ, nếu bạn chuyển kiểu một chuỗi tới một lớp đối tượng và sau đó áp dụng việc chuyển đổi Object đó tới kiểu integer, trình biên dịch sẽ không catch lỗi. Thay vào đó, công cụ vận hành sẽ throw một exception (đưa ra một thông báo ngoại lệ). Việc sử dụng generics cho phép trình biên dịch catch loại lỗi này trước khi chương trình của bạn thi hành. Ngoài ra, bạn có thể chỉ định các ràng buộc để giới hạn các lớp sử dụng trong một generic, cho phép trình biên dịch kiểm tra phát hiện một kiểu không phù hợp.
Hiệu suất được cải thiện (Improved performance) Việc chuyển đổi đòi hỏi boxing và unboxing. Việc sử dụng generics không đòi hỏi phải casting hay boxing, nó cải thiện hiệu suất run-time.
Cách tạo một kiểu Generic
Trước tiên, chúng ta khảo sát các lớp sau đây. Lớp Obj và lớp Gen thực thi chính xác cùng các tác vụ như nhau, tuy nhiên Obj sử dụng lớp Object cho phép kiểu bất kỳ được gởi tới, trong khi đó lớp Gen sử dụng generics:

class Obj{public Object t;public Object u;  public Obj(Object _t, Object _u){t = _t;u = _u;}}  class Gen{public T t;public U u;  public Gen(T _t, U _u){t = _t;u = _u;}}


Trong đó T và U là kiểu dữ liệu (String hay int..) được gửi tới.
Như bạn có thể thấy, lớp Obj có hai thành viên kiểu Object. Lớp Gen có hai thành viên kiểu T và U. Mã lệnh sử dụng sẽ kiểm tra kiểu đối với T và U. Với việc phụ thuộc vào cách mã lệnh sử dụng dùng lớp Gen, T và U có thể là một string, một int, một lớp theo yêu cầu, hoặc sự kết hợp bất kỳ của những cái đó.

Có một sự giới hạn đáng kể đối với việc tạo một lớp generic: mã lệnh generic chỉ hợp lệ nếu nó sẽ biên dịch mọi instance của generic có thể được khởi tạo, dù là một Int, một string, hay bất kỳ một class nào khác. Về bản chất, bạn đã giới hạn khả năng của lớp Object cơ sở khi viết mã lệnh generic. Vì thế bạn có thể gọi phương thức ToString hay GetHashCode bên trong lớp của bạn, tuy nhiên bạn không thể sử dụng toán tử + hoặc > . Cũng các giới hạn này không áp dụng cho consuming code bởi vì consuming code đã khai báo một kiểu cho generic.
Cách dùng một Generic Type
Khi bạn dùng một kiểu generic, bạn phải chỉ định các kiểu cho các generic bất kỳ được sử dụng. Xem xét mã lệnh console application sau, nó sử dụng các lớp Gen và Obj :

// C#// Add two strings using the Obj classObj oa = new Obj("Hello, ", "World!");Console.WriteLine((string)oa.t + (string)oa.u);  // Add two strings using the Gen classGen ga = new Gen("Hello, ", "World!");Console.WriteLine(ga.t + ga.u);  // Add a double and an int using the Obj classObj ob = new Obj(10.125, 2005);Console.WriteLine((double)ob.t + (int)ob.u);  // Add a double and an int using the Gen classGen gb = new Gen(10.125, 2005);Console.WriteLine(gb.t + gb.u);

Nếu bạn thi hành mã lệnh trong một console application, các lớp Obj và Gen sinh ra các kết quả chính xác như nhau. Tuy nhiên, mã lệnh sử dụng lớp Gen trên thực tế sẽ làm việc nhanh hơn bởi vì nó không đòi hỏi boxing và unboxing xuất phát từ lớp Object . Ngoài ra, lập trình viên cũng sẽ có nhiều thời gian thoải mái hơn với việc sử dụng lớp Gen. Đầu tiên, lập trình viên sẽ không phải cast thủ công từ lớp Object tới các kiểu tương thích.

Không có nhận xét nào:

Liên kết quảng cáo :