Generics được thêm từ C# 2.0, là khái niệm quan trọng nhất. Cho phép viết code tái sử dụng, hiệu năng cao, type-safe tại compile-time. Dùng kiểu trong code mà không cần biết trước kiểu đó.
Generics dùng nhiều nơi trong .NET: collections, delegates, async code. Không cần biết size collection trước, dùng được với mọi kiểu element, kể cả custom type. C# hỗ trợ generic types (class, interface...) và generic methods.
Trong generics có type parameters và type arguments, tương tự method có parameters và arguments.
Generic Types
Cú pháp: type parameters trong ngoặc nhọn sau tên kiểu. Ví dụ Locator<T>:
public class Locator<T> { }
Tạo instance: thay T bằng kiểu thực:
var stringLocator = new Locator<string>();
Dùng type parameter trong method class:
public class Locator<T>
{
public IList<T> Items { get; set; }
public T Locate(int index) => Items[index];
}
var stringLocator = new Locator<string>();
string item = stringLocator.Locate(2);
Lợi ích: IntelliSense hiểu kiểu thực. stringLocator.Locate(4) trả về string chứ không phải T. Gán cho kiểu khác (như int) → lỗi compile.
Generic type có thể dùng type parameter làm type argument khi kế thừa base generic hoặc implement interface generic. LinkedList<T> implement IEnumerable<T>.
Generic Methods
Method khai báo type parameter dùng trong method, làm tham số và kiểu trả về. Ví dụ Swap<T>:
public class Swapper
{
public T Swap<T>(ref T first, ref T second)
{
T temp = first;
first = second;
second = temp;
return temp;
}
}
var swapper = new Swapper();
int a = 5, b = 3;
int result = swapper.Swap<int>(ref a, ref b);
// a=3, b=5
Có thể nhiều generic parameters. Dictionary<TKey, TValue> có 2 tham số.
Điều gì có thể là Generic?
Kiểu (trừ enum): class, struct, interface, delegate.
Member của kiểu: chỉ method và nested type. KHÔNG thể generic: field, property, indexer, constructor, event, finalizer.
Ví dụ hoàn chỉnh
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var stringLocator = new Locator<string>()
{
Items = new string[] { "JavaScript", "CSharp", "Golang" }
};
string item = stringLocator.Locate(1);
Console.WriteLine(item); // CSharp
var swapper = new Swapper();
int a = 5, b = 3;
int result = swapper.Swap<int>(ref a, ref b);
Console.WriteLine($"a = {a}, b = {b}"); // a=3, b=5
}
}
public class Locator<T>
{
public IList<T> Items { get; set; }
public T Locate(int index) => Items[index];
}
public class Swapper
{
public T Swap<T>(ref T first, ref T second)
{
T temp = first;
first = second;
second = temp;
return temp;
}
}
Kết quả đầu ra
CSharp
a = 3, b = 5