Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Overloading ใน C# - Method Overloading และ Operator Overloading

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)