C# Generics và C++ Templates đều hỗ trợ parameterized types (kiểu tham số hóa) — viết code một lần, dùng cho nhiều kiểu dữ liệu. Tuy nhiên có khác biệt bản chất về mô hình triển khai và khả năng.
Bảng so sánh chi tiết
| Tiêu chí | C# Generics | C++ Templates |
|---|---|---|
| Mô hình triển khai | Runtime (CLR) — code chia sẻ (shared code) cho reference types; instantiation tại runtime | Compile-time — code bloat (mỗi instantiation sinh code riêng) |
| Type parameter constraints | Hỗ trợ ràng buộc: where T : class, struct, new(), interface, base | Không có constraints (SFINAE, concepts C++20) |
| Explicit specialization | Không hỗ trợ | Hỗ trợ (template specialization) |
| Partial specialization | Không hỗ trợ | Hỗ trợ |
| Non-type template parameters | Không hỗ trợ (chỉ type parameters) | Hỗ trợ (int, pointer, reference, template template) |
| Default type parameters | Không hỗ trợ (từ C# 10 có default interface method, nhưng không phải generic type param) | Hỗ trợ (template<typename T = int>) |
| Type parameter làm base class | Không được (class Derived : T {} illegal) | Được (template<typename T> class Derived : T {}) |
| Runtime type info | Giữ nguyên type info tại runtime (reified generics) | Type erasure (mất info tại runtime, trừ RTTI) |
| Generic variance | Covariance (out) & Contravariance (in) cho interface/delegate | Không có khái niệm variance (template instantiation độc lập) |
| Code bloat | Thấp (shared implementation cho ref types) | Cao (mỗi instantiation = code riêng) |
| Compile time | Nhanh (generic metadata chỉ compile 1 lần) | Chậm (template instantiation heavy) |
| Debugging | Dễ (mã nguồn gốc) | Khó (template instantiation code) |
Ví dụ minh họa
C# Generics
// Constraint: T phải có constructor không tham số
public class Repository where T : class, new() {
public T Create() => new T();
}
// Variance: IEnumerable - covariant
IEnumerable strings = new List();
IEnumerable
C++ Templates
// Non-type template parameter
template
struct FixedArray { int data[N]; };
// Template specialization
template<>
struct Hash { size_t operator()(const string& s) const { ... } };
// Template template parameter
template class Container>
void Process(Container c) { ... }
Khi nào dùng cái nào?
- C# Generics: Ứng dụng nghiệp vụ, type safety, runtime flexibility, reflection, DI container.
- C++ Templates: Metaprogramming, compile-time computation, high-performance library (STL, Eigen), zero-overhead abstraction.
Lưu ý
C# Generics gần hơn với Java Generics (type erasure) nhưng khác ở chỗ: reified tại runtime (CLR biết T là gì) — cho phép typeof(T), default(T), new T() (với constraint), reflection.