Generic

Generic — C# (Reified) vs TypeScript (Erased)

Khác biệt cốt lõi runtime — C# generic giữ type info, TypeScript xoá hết. Implication thực tế.

Tổng quan — Reified vs Erased

C# / Java (modern)TypeScript / Java (legacy)
Generic info ở runtime✅ Reified❌ Erased
typeof(List<int>) runtimeKhác typeof(List<string>)Cùng Array
Tạo instance trong genericnew T() (với constraint)❌ Không trực tiếp
Overload theo generic type✅ Khác Foo(int) vs Foo(string)
Reflection generic✅ Đầy đủ
Performance value typeKhông boxingN/A (TS chỉ compile-time)
Câu PV đặc thù:"C# generic và TypeScript generic khác nhau ra sao?"

"C# generic là reified — runtime giữ thông tin type cụ thể. List<int>List<string> là 2 type khác nhau ở runtime, có thể overload theo type này, dùng reflection inspect.

TypeScript generic là erased — chỉ tồn tại compile-time. Sau khi compile sang JS, mọi generic biến mất. Không thể T extends Animal ? new T() : ... ở runtime — JS không biết T là gì."

1. Code minh hoạ khác biệt

// Có thể tạo instance từ T (cần constraint new())
public class Factory<T> where T : new() {
    public T Create() => new T();
}

// Có thể inspect type T ở runtime
public class Logger<T> {
    public void Log(T value) {
        Console.WriteLine($"Type: {typeof(T).Name}");
        Console.WriteLine($"Value: {value}");
    }
}

var l = new Logger<int>();
l.Log(42);
// Type: Int32
// Value: 42

// typeof so sánh cụ thể
Console.WriteLine(typeof(List<int>) == typeof(List<string>));  // False

2. Hệ quả thực tế

A. Tạo instance từ generic

// C# — OK với new() constraint
public T CreateNew<T>() where T : new() => new T();
// TS — phải truyền constructor
function createNew<T>(Ctor: new () => T): T {
    return new Ctor();
}

createNew(User);    // OK

B. Check type runtime

// C# — typeof
public void Handle<T>(T value) {
    if (typeof(T) == typeof(string)) Console.WriteLine("string!");
    if (value is User u) Console.WriteLine(u.Name);
}
// TS — không check generic, chỉ check value
function handle<T>(value: T) {
    // if (T === string)  // ❌
    if (typeof value === "string") console.log("string!");
    if (value && typeof value === "object" && "name" in value) {
        // narrow
    }
}

C. Overload theo generic type

// C# — overload theo type param
public class Cache {
    public string Get<T>() where T : class => "ref";
    // public string Get<T>() where T : struct => "val";  // ❌ Constraint không phân biệt overload — sẽ là cách khác
}

// Workaround: dùng `is`
public string GetTypeName<T>(T value) {
    return value switch {
        string => "string",
        int => "int",
        _ => "object"
    };
}
// TS — function overload declaration
function get(t: "string"): string;
function get(t: "number"): number;
function get(t: string): any { /* impl */ }

D. Cast / as

// C# — runtime check
object o = "hello";
string s = o as string;            // s = "hello"
int? n = o as int?;                // n = null (runtime check)
// TS — compile-time only
const o: unknown = "hello";
const s = o as string;             // compile pass, không check runtime
const n = o as number;             // ⚠️ pass compile, sai logic
Bẫy TS lớn:as không validate runtime. Để safe runtime → dùng Zod / Valibot / io-ts validate sau parse JSON.

3. Performance — boxing

C# generic = no boxing với value type.
List<int> ints = new();           // Lưu int thẳng trên heap array
ArrayList list = new();           // ❌ Lưu object — mỗi int phải BOX
list.Add(1);                      // boxing → object trên heap

// C# generic compile ra **specialized IL** cho mỗi value type instantiation
// → List<int> implementation # List<long> implementation
TS: không có khái niệm value type, mọi thứ là object → không có boxing.

4. Variance khác biệt

  • C#: variance phải khai báo explicit (out T, in T). Chỉ cho interface và delegate.
  • TS: variance auto-inferred. Có thể annotate explicit out/in (4.7+) nhưng không bắt buộc.

5. Generic constraint — khả năng

C#TS
T : class (ref type)T extends object
T : struct (value type)
T : new()– (truyền Ctor param)
T : InterfaceT extends Interface
T : BaseClassT extends BaseClass
T : enum (C# 7.3+)
T : INumber<T> (C# 11+)– (use number)
T : U (linked params)T extends U
keyof T
T extends "literal"
Conditional T extends X ? A : B
infer trong constraint
Mapped types
Template literal types
TS có type-level programming mạnh hơn C# rất nhiều — conditional, mapped, infer, template literal. Đổi lại C# có runtime info đầy đủ.

6. Reflection

// C# — full runtime introspection
var type = typeof(List<int>);
foreach (var arg in type.GetGenericArguments()) {
    Console.WriteLine(arg.Name);    // Int32
}

// Tạo instance runtime
var generic = typeof(List<>).MakeGenericType(typeof(string));
var instance = Activator.CreateInstance(generic);    // List<string>
// TS — không có. Phải dùng decorator metadata (TC39 stage 3, stable 5.9)
class User {}
// reflect-metadata package + decorator để emit metadata runtime

7. Khi nào điều này thực sự quan trọng?

Scenario cần Reified (C#):
  • Generic Factory với new().
  • Reflection-based ORM (EF Core, Dapper).
  • JSON serializer biết type chính xác để map.
  • Dependency Injection resolve IRepository<User> runtime.
Scenario chỉ cần Erased (TS):
  • Type safety compile-time.
  • API client typed.
  • Form validation.
  • Mọi web app frontend / Node backend tiêu chuẩn.
→ TS erased là đủ cho 95% web work. C# reified cho lib enterprise + ORM.

8. Pattern thay thế trong TS cho thiếu reified

A. Class as runtime token

class User { id = 0; name = ""; }

function create<T>(Ctor: new () => T): T {
    return new Ctor();
}

const u = create(User);     // typed User

B. Schema-first

import { z } from "zod";

const UserSchema = z.object({ id: z.number(), name: z.string() });
type User = z.infer<typeof UserSchema>;

const u = UserSchema.parse(jsonData);   // runtime validate + type infer

C. Decorator + metadata (NestJS, TypeORM style)

@Entity()
class User {
    @PrimaryGeneratedColumn() id!: number;
    @Column() name!: string;
}

Decorator emit metadata reflect-metadata package — ORM dùng runtime.

© 2026 .NET Fresher Guide. All rights reserved.

Về Trang Web

Hướng dẫn toàn diện để chuẩn bị phỏng vấn vị trí .NET Fresher với nội dung từ lý thuyết đến thực hành.