Operator Overloading ใน C#
C# อนุญาตให้กำหนดพฤติกรรมของตัวดำเนินการ (operators) สำหรับประเภทข้อมูลที่ผู้ใช้สร้างเอง (user-defined types) เช่น struct และ class เรียกว่า Operator Overloading ใช้คีย์เวิร์ด operator ตามด้วยสัญลักษณ์ตัวดำเนินการ
ตัวดำเนินการที่โอเวอร์โหลดได้/ไม่ได้
| กลุ่ม | ตัวดำเนินการ | สถานะ |
|---|---|---|
| Unary | +, -, !, ~, ++, -- | ✅ โอเวอร์โหลดได้ |
| Binary | +, -, *, /, % | ✅ โอเวอร์โหลดได้ |
| Comparison | ==, !=, <, >, <=, >= | ✅ โอเวอร์โหลดได้ (ต้องทำเป็นคู่) |
| Conditional Logical | &&, || | ❌ ไม่ได้โดยตรง (แต่ &, | ได้) |
| Assignment | +=, -=, *=, /=, %= | ❌ ไม่ได้ (แต่ทำงานอัตโนมัติจาก binary) |
| Others | =, ., ?:, ->, new, is, sizeof, typeof | ❌ ไม่ได้ |
ไวยากรณ์การโอเวอร์โหลด
public static ReturnType operator OperatorSymbol(ParameterType operand)
{
// unary operator
}
public static ReturnType operator OperatorSymbol(ParameterType left, ParameterType right)
{
// binary operator
}
ตัวอย่างโค้ดสมบูรณ์: โอเวอร์โหลด + สำหรับคลาส Box
using System;
namespace OperatorOvlApplication
{
class Box
{
private double length;
private double breadth;
private double height;
public double GetVolume() => length * breadth * height;
public void SetLength(double len) => length = len;
public void SetBreadth(double bre) => breadth = bre;
public void SetHeight(double hei) => height = hei;
// Overload + operator
public static Box operator +(Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
}
class Tester
{
static void Main(string[] args)
{
Box box1 = new Box();
Box box2 = new Box();
Box box3 = new Box();
double volume = 0.0;
box1.SetLength(6.0); box1.SetBreadth(7.0); box1.SetHeight(5.0);
box2.SetLength(12.0); box2.SetBreadth(13.0); box2.SetHeight(10.0);
volume = box1.GetVolume();
Console.WriteLine("ปริมาตร Box1: {0}", volume);
volume = box2.GetVolume();
Console.WriteLine("ปริมาตร Box2: {0}", volume);
// ใช้ตัวดำเนินการ + ที่โอเวอร์โหลด
box3 = box1 + box2;
volume = box3.GetVolume();
Console.WriteLine("ปริมาตร Box3: {0}", volume);
Console.ReadKey();
}
}
}
ผลลัพธ์
ปริมาตร Box1: 210
ปริมาตร Box2: 1560
ปริมาตร Box3: 5400
แนวทางปฏิบัติที่ดี (Best Practices)
- โอเวอร์โหลดเฉพาะเมื่อมีความหมายที่ชัดเจนและเป็นธรรมชาติ
- ควรโอเวอร์โหลดคู่กัน (==, !=) และ (<, >), (<=, >=)
- คืนค่าใหม่ แล้วไม่ควรแก้ไข operand เดิม (immutable behavior)
- พิจารณา implement
IEquatable<T>และIComparable<T>พร้อมกัน - สำหรับ struct ควร override
EqualsและGetHashCodeด้วย