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

แนวคิดของ Delegate ใน C#


ถ้ามาพื้นฐาน C Delegate คล้าย Function Pointer แต่ใน C# มีความสามารถมากกว่ามาก บทความนี้อธิบายแนวคิด Delegate และการใช้งานจริง

Delegate ให้ระดับ Indirection (การอ้อม) บรรจุ Code ไว้ใน Object สามารถส่งผ่านและ Execute แบบ Type-Safe แทนที่จะ Execute ทันที Code ถูกบรรจุใน Object สามารถทำหลายอย่างกับ Object นั้น หนึ่งในนั้นคือ Execute พฤติกรรมที่บรรจุอยู่

Delegate ช่วยเขียน Higher-Order Functions (ฟังก์ชันที่รับฟังก์ชันเป็นพารามิเตอร์หรือคืนฟังก์ชัน) Delegate Type กำหนด Method Signature ที่ Delegate สามารถแทนได้ (Return Type และ Parameter Types) ตัวอย่าง Transformer แทนเมธอดที่รับและคืน int:

delegate int Transformer(int x);

กำหนดเมธอด (Lambda, Instance, Static) ให้กับ Transformer instance:

Transformer square = x => x * x;
Transformer cube = x => x * x * x;
Console.WriteLine(square(3)); // 9
Console.WriteLine(cube(5)); // 125

เมื่อไหร่ควรใช้ Delegate?

ใช้เมื่อ Code ที่ต้องการ Execute Action ไม่ทราบรายละเอียด Action แต่ทราบ Interface ของ Action ในโปรแกรมมักเจอสถานการณ์ต้อง Execute Action แต่นลไว้ก่อนว่าจะเรียกเมธอดไหน Delegate แก้ปัญหานี้โดยแทนที่พฤติกรรมด้วย Delegate แล้วส่ง Concrete Instance ตาม Context

Delegate ต้องการ 4 ขั้นตอน:

1) ประกาศ Delegate Type

Delegate Type คือ Definition ของฟังก์ชันที่แทน (Parameter Types และ Return Type) เช่น:

delegate int Processor(int numOne, int numTwo);

2) เขียน Code ใน Method ที่มี Signature ตรงกัน

static int Add(int a, int b) => a + b;
static int Subtract(int a, int b) => a - b;

3) สร้าง Delegate Instance

Processor p1 = new Processor(Add);
Processor p2 = new Processor(Subtract);

4) เรียกใช้ (Invoke) Delegate Instance

int sum = p1.Invoke(3, 5); // หรือ p1(3, 5)
int diff = p2(10, 6);

การรวมและลบ Delegate (Multicast)

System.Delegate มี Static Methods Combine และ Remove

Combine

สร้าง Delegate ใหม่ที่รวม Invocation List เรียงลำดับ เรียก Invoke จะ Execute ทุก Action ตามลำดับ หาก Action ใดโยน Exception Action ถัดไปจะไม่ทำงาน

public static Delegate Combine(params Delegate[] delegates);

Remove

ลบ Invocation List ของ Delegate หนึ่งออกจากอีกตัว คืน Delegate ใหม่

public static Delegate Remove(Delegate source, Delegate value);

สรุป

  • Delegate บรรจุพฤติกรรมด้วย Type และ Parameters เฉพาะ (คล้าย Single-Method Interface)
  • Type Signature กำหนดว่ามีเมธอดไหนบ้างที่สร้าง Instance ได้ และ Signature สำหรับ Invoke
  • สร้าง Instance ต้องมี Method ที่ต้องการ Execute เมื่อ Invoke
  • Delegate Instances เป็น Immutable (เหมือน String)
  • แต่ละ Instance มี Invocation List (รายการ Action)
  • Delegate สามารถ Combine และ Remove ได้

ตัวอย่างโค้ดครบ

using System;

class Program
{
    delegate int Transformer(int x);
    delegate int Processor(int a, int b);

    static void Main()
    {
        Transformer square = x => x * x;
        Transformer cube = x => x * x * x;
        Console.WriteLine(square(3)); // 9
        Console.WriteLine(cube(5));   // 125

        Processor p1 = new Processor(Add);
        Processor p2 = new Processor(Subtract);
        Console.WriteLine(p1.Invoke(3, 5)); // 8
        Console.WriteLine(p2(10, 6));       // 4
    }

    static int Add(int a, int b) => a + b;
    static int Subtract(int a, int b) => a - b;
}

ผลลัพธ์

9
125
8
4