Generic trong C#

Generic trong C# cho phép bạn trì hoãn đặc tả (Specification) của kiểu dữ liệu của việc lập trình các phần tử trong một lớp hoặc một phương thức, tới khi nó thực sự được sử dụng trong chương trình. Nói cách khác, Generic cho phép bạn viết một lớp hoặc phương thức có thể làm việc với bất kỳ kiểu dữ liệu nào.

Có thể hiểu generic trong C# là một kiểu dữ liệu, cũng giống như các kiểu dữ liệu int, string,... nhưng khác ở chỗ nó không phải một kiểu cụ thể mà có thể là bất kỳ kiểu nào. Với generic, code được tái sử dụng dễ dàng hơn, trình biên dịch bắt lỗi cũng dễ hơn và bạn không còn phải ép kiểu từ object nữa.

Bạn viết các specification cho lớp và phương thức, với các tham số có thể thay thế cho các kiểu dữ liệu. Khi Compiler bắt gặp một constructor cho một lớp hoặc một lời gọi hàm cho phương thức, nó tạo code để xử lý kiểu dữ liệu cụ thể đó. Dưới đây là ví dụ đơn giản sẽ giúp bạn hiểu khái niệm này.

using System; using System.Collections.Generic; namespace VdGeneric { public class MyGenericArray<T> { private T[] array; public MyGenericArray(int size) { array = new T[size + 1]; } public T getItem(int index) { return array[index]; } public void setItem(int index, T value) { array[index] = value; } } class Tester { static void Main(string[] args) { Console.WriteLine("Ví dụ về Generic trong C#");
Console.WriteLine("-------------------------"); //Khai báo mảng số nguyên. MyGenericArray<int> intArray = new MyGenericArray<int>(5); //Thiết lập giá trị. for (int c = 0; c < 5; c++) { intArray.setItem(c, c*5); } //Trích xuất giá trị. for (int c = 0; c < 5; c++) { Console.Write(intArray.getItem(c) + " "); } Console.WriteLine(); //Khai báo mảng ký tự. MyGenericArray<char> charArray = new MyGenericArray<char>(5); //Thiết lập giá trị. for (int c = 0; c < 5; c++) { charArray.setItem(c, (char)(c+97)); } //Trích xuất giá trị và in ra màn hình. for (int c = 0; c< 5; c++) { Console.Write(charArray.getItem(c) + " "); } Console.WriteLine(); Console.ReadKey(); } } }


Sử dụng lệnh Console.ReadKey(); để xem kết quả một cách rõ ràng hơn.

Biên dịch và chạy chương trình C# trên bạn sẽ nhận được kết quả như sau:

Ví dụ về Generic trong C#
-------------------------
0 5 10 15 20
a b c d e

Tính năng của Generic trong C#

Generic là một kỹ thuật làm cho chương trình C# của bạn phong phú hơn theo các cách sau:

  • Nó giúp bạn tối đa hóa việc tái sử dụng của code, an toàn kiểu, và hiệu năng.
  • Bạn có thể tạo các lớp generic collection. Thư viện lớp của .Net Framework chứa một số lớp generic collection trong System.Collections.Generic namespace. Bạn có thể sử dụng các lớp generic collection này thay cho các lớp collection trong System.Collections namespace.
  • Bạn có thể tự tạo các Class, Interface, phương thức, Event và Delegate dạng generic.
  • Bạn có thể tạo các lớp generic có khả năng truy cập tới các phương thức trên các kiểu dữ liệu cụ thể.
  • Bạn có thể lấy thông tin về các kiểu được sử dụng trong một kiểu dữ liệu generic tại runtime bởi các phương thức của Reflection.

Các phương thức Generic trong C#

Trong ví dụ trước, chúng ta đã sử dụng một lớp generic, tương tự, chúng ta có thể khai báo một phương thức generic với một tham số kiểu. Ví dụ sau minh họa điều này:

using System; using System.Collections; namespace QTMCsharp { class TestCsharp { static void Swap<T>(ref T lhs, ref T rhs) { T temp; temp = lhs; lhs = rhs; rhs = temp; } static void Main(string[] args) { Console.WriteLine("Ví dụ 2 về Generic trong C#"); Console.WriteLine("--------Ví dụ hoán đổi giá trị--------"); int a, b; char c, d; a = 10; b = 20; c = 'I'; d = 'V'; // Hiển thị các giá trị trước khi hoán đổi. Console.WriteLine("Các giá trị số trước khi gọi hàm swap: "); Console.WriteLine("a = {0}, b = {1}", a, b); Console.WriteLine("Các giá trị chữ trước khi gọi hàm swap:"); Console.WriteLine("c = {0}, d = {1}", c, d); // Gọi hàm swap để hoán đổi giá trị. Swap<int>(ref a, ref b); Swap<char>(ref c, ref d); // Hiển thị các giá trị sau khi hoán đổi: Console.WriteLine("Các giá trị số trước khi gọi hàm swap:"); Console.WriteLine("a = {0}, b = {1}", a, b); Console.WriteLine("Các giá trị chữ trước khi gọi hàm swap:"); Console.WriteLine("c = {0}, d = {1}", c, d); Console.ReadKey(); } } }

Biên dịch và chạy chương trình C# trên sẽ cho kết quả sau:

Ví dụ 2 về Generic trong C#
--------Ví dụ hoán đổi giá trị--------
Các giá trị số trước khi gọi hàm swap:
a = 10, b = 20
Các giá trị chữ trước khi gọi hàm swap:
c = I, d = V
Các giá trị số trước khi gọi hàm swap:
a = 20, b = 10
Các giá trị chữ trước khi gọi hàm swap:
c = V, d = I

Generic Delegate trong C#

Trong C#, bạn có thể định nghĩa một Generic Delegate với các tham số kiểu. Ví dụ:

delegate T NumberChanger<T>(T n);

Ví dụ sau đây minh họa cách sử dụng của generic delegate trong C#:

using System; using System.Collections; delegate T NumberChanger<T>(T n); namespace QTMCsharp { class TestCsharp { static int num = 10; public static int AddNum(int p) { num += p; return num; } public static int MultNum(int q) { num *= q; return num; } public static int getNum() { return num; } static void Main(string[] args) { Console.WriteLine("Generic Delegate trong C#"); Console.WriteLine("---------------------------"); //Tạo các đối tượng delegate NumberChanger<int> nc1 = new NumberChanger<int>(AddNum); NumberChanger<int> nc2 = new NumberChanger<int>(MultNum); //Gọi hai phương thức sử dụng các đối tượng delegate nc1(25); Console.WriteLine("1 - Giá trị của num là: {0}", getNum()); nc2(5); Console.WriteLine("2 - Giá trị của num là: {0}", getNum()); Console.ReadKey(); } } }

Khi chạy chương trình trên bạn sẽ nhận được kết quả như sau:

Generic Delegate trong C#
---------------------------
1 - Giá trị của num là: 35
2 - Giá trị của num là: 175

Theo Tutorialspoint

Bài trước: Collection trong C#

Bài tiếp: Phương thức nặc danh trong C#

Thứ Sáu, 03/08/2018 11:06
51 👨 258