Operator Overloading ใน C# - สิ่งที่ Overload ได้และไม่ได้
C# อนุญาตให้ overload operator ส่วนใหญ่ แต่มีข้อจำกัดบางอย่าง
Operator ที่ Overload ได้ ✅
| กลุ่ม | Operators | ประเภท | ตัวอย่าง Signature |
| Unary | + - ! ~ ++ -- | Unary (1 operand) | public static T operator +(T a) |
| Unary | true false | Unary (bool) | public static bool operator true(T a) |
| Binary Arithmetic | + - * / % | Binary (2 operands) | public static T operator +(T a, T b) |
| Comparison | == != < > <= >= | Binary (return bool) | public static bool operator ==(T a, T b) |
| Bitwise | & | ^ << >> | Binary | public static T operator &(T a, T b) |
| Conversion | implicit explicit | Conversion | public static implicit operator T(Other o) |
Operator ที่ Overload ไม่ได้ ❌
| กลุ่ม | Operators | เหตุผล |
| Conditional Logical | && || | Short-circuit evaluation - ใช้ overload & และ | แทน (พร้อม operator true/false) |
| Assignment | = += -= *= /= %= &= |= ^= <<= >>= | Assignment เป็น built-in syntax ไม่ใช่ operator จริง |
| Member Access | . (dot) | Language syntax |
| Indexing | [] | ใช้ Indexer property แทน |
| Method Call | () | ใช้ Delegate/Func แทน |
| Lambda | => | Syntax |
| Type Related | new, is, as, typeof, sizeof, default | Keywords/Syntax |
| Ternary | ?: | Syntax |
| Null-coalescing | ?? ??= | Syntax (C# 8+) |
กฎการ Overload
- ต้องเป็น static และ public
- อย่างน้อยหนึ่งพารามิเตอร์** ต้องเป็น containing type (class/struct ที่ overload อยู่)
- Unary operator: 1 parameter
- Binary operator: 2 parameters
- Conversion operator: 1 parameter, return type ต้องเป็น containing type หรือ parameter type
- Comparison operators ต้อง overload เป็นคู่: == กับ !=, < กับ >, <= กับ >=
ตัวอย่าง: Complex Number
public struct Complex
{
public double Real { get; }
public double Imag { get; }
public Complex(double real, double imag) => (Real, Imag) = (real, imag);
// Binary +
public static Complex operator +(Complex a, Complex b)
=> new Complex(a.Real + b.Real, a.Imag + b.Imag);
// Binary -
public static Complex operator -(Complex a, Complex b)
=> new Complex(a.Real - b.Real, a.Imag - b.Imag);
// Binary * (complex multiplication)
public static Complex operator *(Complex a, Complex b)
=> new Complex(
a.Real * b.Real - a.Imag * b.Imag,
a.Real * b.Imag + a.Imag * b.Real
);
// Unary -
public static Complex operator -(Complex a)
=> new Complex(-a.Real, -a.Imag);
// Comparison (ต้องทำคู่)
public static bool operator ==(Complex a, Complex b)
=> a.Real == b.Real && a.Imag == b.Imag;
public static bool operator !=(Complex a, Complex b)
=> !(a == b);
// Implicit conversion from double
public static implicit operator Complex(double d)
=> new Complex(d, 0);
// Explicit conversion to double (magnitude)
public static explicit operator double(Complex c)
=> Math.Sqrt(c.Real * c.Real + c.Imag * c.Imag);
public override string ToString() => $"{Real} + {Imag}i";
public override bool Equals(object obj) => obj is Complex c && this == c;
public override int GetHashCode() => HashCode.Combine(Real, Imag);
}
// ใช้งาน
var c1 = new Complex(1, 2);
var c2 = new Complex(3, 4);
Complex sum = c1 + c2; // 4 + 6i
Complex diff = c1 - c2; // -2 - 2i
Complex prod = c1 * c2; // -5 + 10i
bool eq = c1 == new Complex(1, 2); // true
double mag = (double)c1; // explicit cast: √5 ≈ 2.236
Operator true/false สำหรับ && ||
// ถ้าต้องการให้ && || ทำงานกับ custom type
public static bool operator true(MyType a) => a.IsTrue;
public static bool operator false(MyType a) => !a.IsTrue;
// แล้ว overload & และ |
public static MyType operator &(MyType a, MyType b) => ...;
public static MyType operator |(MyType a, MyType b) => ...;
// ตอนนี้ a && b จะทำงานได้ (evaluate a, ถ้า false คืน a, ไม่เช่นนั้น evaluate b)
Best Practices
- Overload เฉพาะที่มีความหมายทางคณิตศาสตร์/โดเมนชัดเจน
- คงสมบัติทางคณิตศาสตร์ (commutative, associative)
- Override Equals/GetHashCode เมื่อ overload ==/!=
- Implicit conversion ควรไม่สูญเสียข้อมูล (lossless)
- Explicit conversion สำหรับ lossy/narrowing
- เอกสารชัดเจน พร้อม Unit Tests