Class = Reference Type, Struct = Value Type — ความแตกต่างพื้นฐานนี้นำไปสู่พฤติกรรมที่ต่างกันหลายประการ
Comparison Table
| Feature | Class (Reference Type) | Struct (Value Type) |
|---|---|---|
| Memory Allocation | Heap (Managed by GC) | Stack (หรือ Inline ใน Object อื่น) |
| Assignment | Copy Reference (Shallow) | Copy Value (Deep) |
| Nullability | Can be Null | Cannot be Null (Nullable<T> ได้) |
| Inheritance | ✅ Full Support | ❌ No Inheritance (แต่ Implement Interface ได้) |
| Default Constructor | Implicit Parameterless | Implicit Parameterless (Zero-init), ไม่สามารถสร้าง Custom Parameterless ได้ |
| Destructor/Finalizer | ✅ Supported | ❌ Not Supported |
| Field Initializers | Allowed | Not Allowed (Instance Fields) |
| Interface Implementation | ✅ | ✅ |
| Generic Constraints | class | struct |
| Passing to Method | Pass Reference (Pointer) | Pass by Value (Copy) — ใช้ ref/in/out เพื่อ Pass by Reference |
ตัวอย่าง: Assignment Behavior
// Class - Reference Semantics
class PointClass { public int X, Y; }
var c1 = new PointClass { X = 1, Y = 2 };
var c2 = c1; // Copy Reference
c2.X = 10;
Console.WriteLine(c1.X); // 10 — c1 เปลี่ยนไปด้วย!
// Struct - Value Semantics
struct PointStruct { public int X, Y; }
var s1 = new PointStruct { X = 1, Y = 2 };
var s2 = s1; // Copy Value
s2.X = 10;
Console.WriteLine(s1.X); // 1 — s1 ไม่เปลี่ยน!
เมื่อไหร่ใช้ Struct?
- ขนาดเล็ก (< 16-24 bytes)
- Immutable (Readonly Struct)
- มี Lifetime สั้น (Short-lived)
- ไม่ต้องการ Polymorphism
- Performance Critical: Game Dev, Math, Graphics, High-frequency Trading
- Examples:
int, double, DateTime, Guid, Point, Vector, Color
เมื่อไหร่ใช้ Class?
- ขนาดใหญ่ หรือ มี Reference Semantics
- ต้องการ Inheritance / Polymorphism
- Identity สำคัญ (Two Objects with Same Data ≠ Same Object)
- Nullable โดย Nature
- Long-lived Objects
Modern C#: readonly struct / record struct
// Immutable Struct (C# 7.2+)
public readonly struct Point3D {
public double X { get; }
public double Y { get; }
public double Z { get; }
public Point3D(double x, double y, double z) {
X = x; Y = y; Z = z;
}
}
// Record Struct (C# 10+) — Value-based Equality Built-in
public record struct Person(string Name, int Age);
⚠️ Common Pitfalls
- ❌ Boxing: Struct → object / Interface → Allocation + Copy
- ❌ Mutable Structs: ก่อให้เกิด Bugs ยากหา (Copy แล้ว Mutate ตัวไหนไม่ชัดเจน)
- ❌ Large Structs: Copy Cost สูง — ใช้ Class หรือ Pass by Ref (
ref/in)