Value type và reference type khác nhau ở cách biến lưu dữ liệu: biến value type chứa giá trị, biến reference type chứa reference trỏ tới object trên heap.
Hãy hình dung value type như bản photo — mỗi người giữ bản sao riêng. Reference type như link Drive — mọi người cùng sửa trên một file.
Về cơ chế, khi gán a = b với value type, runtime sao chép nội dung (với struct là từng field). Với reference type, chỉ sao chép reference nên hai biến cùng trỏ tới một instance. Hệ quả là khác biệt khi truyền tham số, so sánh và xử lý null. Value type, trừ Nullable<T>, không thể là null và so sánh theo giá trị; reference type có thể là null và so sánh theo reference, trừ các type override Equals như string hay record.
Vị trí lưu trữ không cố định như mô tả cũ "value type luôn ở stack". Value type nằm inline nơi khai báo: biến local thì trên stack, field trong class thì nằm trong object trên heap, khi boxing thì thành object trên heap. Reference type luôn có object trên heap, biến chỉ giữ reference.
struct,enum,int,double,bool,record structlà value type.class,record,interface,delegate,array,stringlà reference type.
Lỗi thường gặp là lạm dụng struct vì nghĩ luôn nhẹ hơn class, hoặc sửa struct trong List<T> qua foreach và ngạc nhiên vì bản gốc không đổi do đang sửa trên bản sao. Lỗi khác là boxing vô ý khi truyền struct vào tham số object hoặc interface, tạo allocation không cần thiết.
Lưu ý: Dùng struct khi giá trị nhỏ, bất biến và mang ngữ nghĩa giá trị; dùng class khi cần identity, chia sẻ trạng thái hoặc kế thừa. Đừng chọn dựa trên "stack nhanh hơn heap" — chi phí thực tế nằm ở kích thước sao chép và áp lực lên GC.