Overloading** ใน C# เป็นเทคนิคของ **Static Polymorphism (Compile-time Polymorphism)** ที่ช่วยให้กำหนด Member หลายตัวที่มี **ชื่อเดียวกัน** แต่ **Signature ต่างกัน** (พารามิเตอร์ต่างกัน)
1. Function/Method Overloading
สร้างเมธอดหลายตัวชื่อเดียวกัน แตกต่างกันที่:
- จำนวนพารามิเตอร์ (Number of Parameters)
- ชนิดข้อมูลพารามิเตอร์ (Parameter Types)
- ลำดับพารามิเตอร์ (Parameter Order)
- ❌ **ไม่ใช่** Return Type เพียงอย่างเดียว
ตัวอย่าง: จำนวน Arguments ต่างกัน
public class Calculator {
// 2 Parameters
public static int Mul(int a, int b) => a * b;
// 3 Parameters
public static int Mul(int a, int b, int c) => a * b * c;
// 4 Parameters
public static int Mul(int a, int b, int c, int d) => a * b * c * d;
// Different Types
public static double Mul(double a, double b) => a * b;
public static decimal Mul(decimal a, decimal b) => a * b;
}
// ใช้งาน
Console.WriteLine(Calculator.Mul(10, 15)); // 150 (int, 2 args)
Console.WriteLine(Calculator.Mul(8, 13, 20)); // 2080 (int, 3 args)
Console.WriteLine(Calculator.Mul(3, 7, 10, 7)); // 1470 (int, 4 args)
Console.WriteLine(Calculator.Mul(2.5, 4.0)); // 10.0 (double)
ตัวอย่างโค้ดสมบูรณ์
using System;
public class Demo {
public static int MulDisplay(int one, int two) {
return one * two;
}
public static int MulDisplay(int one, int two, int three) {
return one * two * three;
}
public static int MulDisplay(int one, int two, int three, int four) {
return one * two * three * four;
}
}
public class Program {
public static void Main() {
Console.WriteLine("Multiplication of two numbers: " + Demo.MulDisplay(10, 15));
Console.WriteLine("Multiplication of three numbers: " + Demo.MulDisplay(8, 13, 20));
Console.WriteLine("Multiplication of four numbers: " + Demo.MulDisplay(3, 7, 10, 7));
}
}
ผลลัพธ์
Multiplication of two numbers: 150
Multiplication of three numbers: 2080
Multiplication of four numbers: 1470
Overloading กับ Optional Parameters / Default Values
// แทน Overloading หลายตัว ใช้ Optional Parameters (C# 4+)
public static int Mul(int a, int b, int c = 1, int d = 1) => a * b * c * d;
// ใช้งาน
Mul(2, 3); // 6
Mul(2, 3, 4); // 24
Mul(2, 3, 4, 5); // 120
2. Operator Overloading
กำหนดพฤติกรรมของ Operators (+, -, ==, etc.) สำหรับ **Custom Types (Struct/Class)**
Syntax
public static ReturnType operator OperatorSymbol(ParameterList) { ... }
Operators ที่ Overload ได้/ไม่ได้
| กลุ่ม | Operators | Overload? |
|---|---|---|
| Unary | + - ! ~ ++ -- true false |
✅ ได้ |
| Binary Arithmetic | + - * / % |
✅ ได้ |
| Comparison | == != < > <= >= |
✅ ได้ (ต้องคู่กัน: == กับ !=, < กับ >, <= กับ >=) |
| Bitwise | & | ^ << >> |
✅ ได้ |
| Logical | && || |
❌ ไม่ได้โดยตรง (แต่ได้ผ่าน true/false + &/|) |
| Assignment | += -= *= /= %= &= |= ^= <<= >>= |
❌ ไม่ได้ (Compound Assignment ใช้ Operator พื้นฐาน) |
| Others | = . ?: ?? new is as sizeof typeof |
❌ ไม่ได้ |
| Conversion | implicit explicit |
✅ ได้ (User-defined Conversions) |
ตัวอย่าง Operator Overloading สมบูรณ์
using System;
public struct Vector2 {
public double X, Y;
public Vector2(double x, double y) { X = x; Y = y; }
// Binary +
public static Vector2 operator +(Vector2 a, Vector2 b) {
return new Vector2(a.X + b.X, a.Y + b.Y);
}
// Binary -
public static Vector2 operator -(Vector2 a, Vector2 b) {
return new Vector2(a.X - b.X, a.Y - b.Y);
}
// Unary -
public static Vector2 operator -(Vector2 v) {
return new Vector2(-v.X, -v.Y);
}
// Comparison == (ต้องมี != คู่กัน)
public static bool operator ==(Vector2 a, Vector2 b) {
return a.X == b.X && a.Y == b.Y;
}
public static bool operator !=(Vector2 a, Vector2 b) {
return !(a == b);
}
// Implicit Conversion from Tuple
public static implicit operator Vector2((double X, double Y) tuple) {
return new Vector2(tuple.X, tuple.Y);
}
// Explicit Conversion to Tuple
public static explicit operator (double X, double Y)(Vector2 v) {
return (v.X, v.Y);
}
public override string ToString() => $"({X}, {Y})";
// Required when overloading ==/!=
public override bool Equals(object obj) => obj is Vector2 v && this == v;
public override int GetHashCode() => HashCode.Combine(X, Y);
}
class Program {
static void Main() {
Vector2 a = (3, 4); // Implicit from Tuple
Vector2 b = (1, 2);
Vector2 sum = a + b; // (4, 6)
Vector2 diff = a - b; // (2, 2)
Vector2 neg = -a; // (-3, -4)
Console.WriteLine($"Sum: {sum}");
Console.WriteLine($"Equal: {a == b}"); // False
Console.WriteLine($"As Tuple: {(double, double)a}"); // Explicit Cast
}
}
Best Practices สำหรับ Operator Overloading
- **Intuitive Semantics**: + ต้องทำงานเหมือน Addition, == ต้องเป็น Equivalence Relation
- **Immutability**: Structs ควร Immutable - Operator คืน Instance ใหม่
- **Consistency**: Overload == ต้อง Override
Equals,GetHashCode,!= - **Don't Overload** เพื่อ Side Effects หรือ Logic ที่ซับซ้อน
- **Math Types** (Vector, Matrix, Complex, Fraction) เหมาะที่สุด
Static vs Dynamic Polymorphism สรุป
| ด้าน | Static (Overloading) | Dynamic (Overriding) |
|---|---|---|
| Binding Time | Compile Time | Runtime |
| Mechanism | Method/Operator Overloading | Virtual/Abstract + Override |
| Performance | เร็วกว่า (Direct Call) | ช้ากว่าเล็กน้อย (Vtable) |
| Extensibility | จำกัด (Compile-time) | สูง (Runtime, Plugins) |