Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Late Binding (Gọi muộn) trong C# - Đa hình động

Late Binding (Gọi muộn / Dynamic Polymorphism) là cơ chế quyết định phương thức nào được gọi tại runtime thay vì compile-time. Trong C#, đạt được qua:

  • Virtual/Override: Polymorphism chuẩn OOP.
  • Abstract class/Interface: Contract bắt buộc implement.
  • dynamic (C# 4+): DLR (Dynamic Language Runtime), bỏ qua compile-time checking.
  • Reflection: MethodInfo.Invoke().

Ví dụ: Virtual/Override (Polymorphism chuẩn)

using System;

namespace PolymorphismDemo
{
    abstract class Shape
    {
        protected int Width, Height;
        public Shape(int w = 0, int h = 0) { Width = w; Height = h; }
        public abstract int Area(); // Abstract method - bắt buộc override
    }
    
    class Rectangle : Shape
    {
        public Rectangle(int w, int h) : base(w, h) { }
        public override int Area() => Width * Height;
    }
    
    class Triangle : Shape
    {
        public Triangle(int w, int h) : base(w, h) { }
        public override int Area() => Width * Height / 2;
    }
    
    class Caller
    {
        // Late binding: method Area() được quyết định tại runtime
        public void CallArea(Shape shape)
        {
            Console.WriteLine($"{shape.GetType().Name} area: {shape.Area()}");
        }
    }
    
    class Program
    {
        static void Main()
        {
            Caller caller = new Caller();
            caller.CallArea(new Rectangle(10, 7)); // Rectangle.Area() gọi ở runtime
            caller.CallArea(new Triangle(10, 5));  // Triangle.Area() gọi ở runtime
            
            // Danh sách shape - polymorphism
            Shape[] shapes = { new Rectangle(5, 5), new Triangle(4, 6) };
            foreach (var s in shapes)
                Console.WriteLine($"{s.GetType().Name}: {s.Area()}");
        }
    }
}

Kết quả

Rectangle area: 70
Triangle area: 25
Rectangle: 25
Triangle: 12

Late Binding với dynamic (C# 4+)

using System;

class Duck
{
    public void Quack() => Console.WriteLine("Quack!");
    public void Fly() => Console.WriteLine("Flying!");
}

class Robot
{
    public void Quack() => Console.WriteLine("Beep boop!");
    // Không có Fly()
}

class Program
{
    static void Main()
    {
        dynamic duck = new Duck();
        dynamic robot = new Robot();
        
        MakeItQuack(duck);   // OK: Duck có Quack()
        MakeItQuack(robot);  // OK: Robot có Quack()
        
        // MakeItFly(duck);  // OK
        // MakeItFly(robot); // RuntimeBinderException: Robot không có Fly()
    }
    
    static void MakeItQuack(dynamic obj)
    {
        obj.Quack(); // Resolved tại runtime
    }
}

So sánh Early Binding vs Late Binding

Đặc điểmEarly Binding (Static)Late Binding (Dynamic)
Thời điểm quyết địnhCompile-timeRuntime
Cơ chếMethod overloading, non-virtual callVirtual/override, dynamic, reflection
Hiệu năngNhanh (direct call, inline)Chậm hơn (v-table lookup, DLR cache)
Type safetyCompile-time checkRuntime error nếu missing member
Linh hoạtCứngMềm (plugin, scripting, COM interop)

Khi nào dùng Late Binding?

  • Plugin/Extension system (load assembly động).
  • Interop COM, JavaScript, Python (IronPython).
  • Generic code xử lý kiểu không biết trước.
  • Testing/Mocking.

Lưu ý: Lạm dụng dynamic làm code khó debug, mất IntelliSense, dễ bug runtime. Ưu tiên virtual/override hoặc interface cho polymorphism chuẩn.