🧩 Delegate, Action, Func, Event và EventHandler

1️⃣ Khai báo một delegate

// 📝 Khai báo một delegate kiểu void
public delegate void ShowLog(string message);

⚡ Thực thi một delegate

ShowLog log = null;
log = Info;
log("Hello world !");

// Hoặc dùng cách an toàn hơn
log?.Invoke("Hello world ~");

log = Warning;
log("Testing");

🔗 Thực hiện chain các delegate

ShowLog log = null;
log += Info;
log += Warning;
log?.Invoke("Testing");


2️⃣ Action

Action là một delegate kiểu void.

Action action; // 🔹 tương đương delegate void FunctionABC()
Action<string, int> action1; // 🔹 tương đương delegate void FunctionABC(string s, int i)

💡 Sử dụng Action

Action<string> action2;
action2 = Warning;
action2 += Info;

action2?.Invoke("Testing.....");


3️⃣ Func

Func là một delegate có kiểu trả về, kiểu trả về luôn nằm cuối cùng trong dấu <>.

// 🔹 Func trả về int, không có tham số
Func<int> function1;

// 🔹 Func trả về string, với 2 tham số đầu vào
Func<string, double, string> function2;

🧮 Ví dụ

static int Sum(int a, int b) => a + b;
static int Sub(int a, int b) => a - b;

Func<int, int, int> calculator;
int a = 5, b = 10;

calculator = Sum;
Console.WriteLine($"Tổng: {calculator(a, b)}");

calculator = Sub;
Console.WriteLine($"Hiệu: {calculator(a, b)}");


4️⃣ Sử dụng delegate với biểu thức lambda

⚡ Delegate void

Action<string> Notification = s => Console.WriteLine(s);
Notification?.Invoke("This is a message");

Action Notification1 = () => Console.WriteLine("Hello !");
Notification1?.Invoke();

Action<string, string> welcome2 = (msg, name) => Console.WriteLine(msg + " " + name);
welcome2?.Invoke("Hello", "John");

🧮 Delegate có kiểu trả về

Func<int, int, int> calculator = (x, y) => x + y;
Console.WriteLine($"Result: {calculator(5, 6)}");

// 🔹 Duyệt qua mảng và tính căn bậc 2
int[] myArray = { 1, 2, 3, 4, 45, 56, 6, 54 };
var result = myArray.Select(x => Math.Sqrt(x));
foreach (var item in result) Console.WriteLine(item);

// 🔹 Hiển thị các số chia hết cho 2
myArray.ToList().ForEach(x => { if (x % 2 == 0) Console.WriteLine(x); });

🧩 Filter bằng expression

static List<int> FilterByPredicate(Func<int, bool> expression, int[] array)
{
    return array.Where(expression).ToList();
}

// 🔹 Gọi thực thi
var evenNumbers = FilterByPredicate(x => x % 2 == 0, myArray);
var oddNumbers = FilterByPredicate(x => x % 2 != 0, myArray);
var rangeNumbers = FilterByPredicate(x => x > 10 && x < 20, myArray);


5️⃣ Event và EventHandler

5.1 📡 Sử dụng Event

public delegate void InputNumberEvent(int x);

class UserInput
{
    public event InputNumberEvent inputNumberEvent;

    public void Input()
    {
        do
        {
            Console.WriteLine("Input a number: ");
            string s = Console.ReadLine();
            int i = Int32.Parse(s);
            inputNumberEvent?.Invoke(i);
        } while (true);
    }
}

🔢 Sử dụng với các lớp tính toán

class SqrtCalculator
{
    public void Subscribe(UserInput input) => input.inputNumberEvent += SQRT;
    public void SQRT(int i) => Console.WriteLine($"SQRT of {i} = {Math.Sqrt(i)}");
}

class SquareCalculator
{
    public void Subscribe(UserInput input) => input.inputNumberEvent += SQUARE;
    public void SQUARE(int i) => Console.WriteLine($"Square of {i} = {Math.Pow(i, 2)}");
}

⚡ Thực thi Event

UserInput userInput = new UserInput();
userInput.inputNumberEvent += x => Console.WriteLine("You have just input a number to the system...");

var sqrtCalc = new SqrtCalculator();
sqrtCalc.Subscribe(userInput);

var squareCalc = new SquareCalculator();
squareCalc.Subscribe(userInput);

userInput.Input();


5.2 🛠️ Sử dụng EventHandler

class DataInput : EventArgs
{
    public int Data { get; set; }
    public DataInput(int x) => Data = x;
}

class UserInput
{
    public event EventHandler inputNumberEvent;

    public void Input()
    {
        do
        {
            Console.WriteLine("Input a number: ");
            string s = Console.ReadLine();
            int i = Int32.Parse(s);
            inputNumberEvent?.Invoke(this, new DataInput(i));
        } while (true);
    }
}

🔢 Các lớp tính toán sử dụng EventHandler

class SqrtCalculator
{
    public void Subscribe(UserInput input) => input.inputNumberEvent += SQRT;
    public void SQRT(object sender, EventArgs e)
    {
        int i = ((DataInput)e).Data;
        Console.WriteLine($"SQRT of {i} = {Math.Sqrt(i)}");
    }
}

class SquareCalculator
{
    public void Subscribe(UserInput input) => input.inputNumberEvent += SQUARE;
    public void SQUARE(object sender, EventArgs e)
    {
        int i = ((DataInput)e).Data;
        Console.WriteLine($"Square of {i} = {Math.Pow(i, 2)}");
    }
}

⚡ Thực thi EventHandler

UserInput userInput = new UserInput();
userInput.inputNumberEvent += (sender, e) =>
{
    int i = ((DataInput)e).Data;
    Console.WriteLine($"You have just input a number {i} to the system...");
};

var sqrtCalc = new SqrtCalculator();
sqrtCalc.Subscribe(userInput);

var squareCalc = new SquareCalculator();
squareCalc.Subscribe(userInput);

userInput.Input();


Tối ưu:

  • Thêm icon giúp dễ đọc và phân biệt sections.
  • Giữ các code block rõ ràng.
  • Comment sinh động và dễ hiểu.