CodeGym /Các khóa học /C# SELF /Cú pháp biểu thức lambda ( =&...

Cú pháp biểu thức lambda ( =>)

C# SELF
Mức độ , Bài học
Có sẵn

1. Giới thiệu

Có thể bạn chưa biết, nhưng một trong những câu hỏi ưa thích ở phỏng vấn là “Bạn biết gì về biểu thức lambda?”. Tại sao lại hỏi? Vì đó là một thứ rất tiện và "thời thượng" trong C#, cho phép viết ít code hơn và biểu đạt rõ ràng hơn. Nếu anonymous methods là viết thư tay, thì biểu thức lambda là gửi tin nhắn trên messenger: nhanh, gọn, và đôi khi còn có emoji (đúng hơn là gần như vậy).

Biểu thức lambda xuất hiện trong C# từ phiên bản 3.0 và kể từ đó lan rộng khắp nơi: trong LINQ, event handlers, threads, collections và thậm chí các thư viện AI trên .NET.

Biểu thức lambda — là cách khai báo một method ngay trong thân code, "tại chỗ", không cần tên, siêu ngắn và rõ ràng. Cú pháp cơ bản luôn trông như sau:

(tham_số) => biểu_thức_hoặc_block_code

Mũi tên này => được gọi là “lambda operator” hoặc “arrow”.

Một ví dụ ví von nhỏ

Hãy nhớ lại cách bạn viết công thức nấu ăn: “Lấy táo, cắt nó, cho vào bát”.
Trong C# sẽ là:

(tao) => cat(tao)

2. Chuyển anonymous method sang lambda

Giả sử chúng ta có một delegate:

delegate int SquareDelegate(int x);

Anonymous method sẽ trông như sau:

SquareDelegate sq = delegate(int x) {
    return x * x;
};

Còn bây giờ tương đương bằng biểu thức lambda:

SquareDelegate sq = (int x) => { return x * x; };

Nhưng C# có thể suy ra kiểu, nên ta có thể rút ngắn thêm:

SquareDelegate sq = x => x * x;

Ngắn gọn tuyệt vời!

So sánh với phương thức "bình thường" và anonymous function

Cách Khai báo Chỗ dùng Nhược điểm
Named method Trong lớp Mọi nơi Cần tên, nhiều code hơn
Anonymous method Trong code Chỉ với delegates Cú pháp cồng kềnh hơn
Lambda expression Trong code Mọi chỗ với delegates Đôi khi kiểu không rõ ràng

3. Cú pháp biểu thức lambda: các biến thể

Tham số

Không có tham số:

Action hello = () => Console.WriteLine("Xin chào, thế giới!");

Một tham số (có thể bỏ ngoặc):

Func<int, int> inc = x => x + 1;

Nhiều tham số (cần ngoặc):

Func<int, int, int> sum = (a, b) => a + b;

Thân lambda

Một biểu thức — không cần braces và return:

x => x * x

Block code — dùng braces, cần return:

(x, y) =>
{
    int z = x + y;
    return z * z;
}

Kiểu tham số

Thường không cần chỉ định kiểu — compiler sẽ suy. Nhưng nếu muốn, cũng được:

(x, y) => x + y      // Compiler tự suy kiểu.
(int x, int y) => x + y  // Có thể chỉ định rõ.

4. Một số lưu ý và ví dụ thực tế hơn

Sử dụng với collections

Nhớ ứng dụng mini học của chúng ta (ví dụ danh sách users)? Giả sử có mảng số:

int[] numbers = { 1, 2, 3, 4, 5 };

Cần chọn các số chẵn:

var evenNumbers = numbers.Where(n => n % 2 == 0);

Ở đây Where — extension method của LINQ, còn điều kiện là lambda filter của chúng ta.

Truyền vào method

Giả sử ta có một delegate method:

public delegate bool Filter(int number);

public static int[] FilterNumbers(int[] data, Filter predicate)
{
    var result = new List<int>();
    foreach (var n in data)
        if (predicate(n))
            result.Add(n);
    return result.ToArray();
}

Bây giờ truyền lambda:

int[] evens = FilterNumbers(numbers, n => n % 2 == 0);

Lambda làm event handler

button.Click += (sender, args) => Console.WriteLine("Nút được nhấn!");

5. Lambda và các delegate generic chuẩn

Khó tưởng tượng lambda mà thiếu Func<>, Action<>Predicate<>. Đó là các kiểu delegate tiện dụng:

  • Action — không trả về gì.
  • Func — trả về giá trị.
  • Predicate — trả về bool, thường dùng cho filtering.

Ví dụ với Action:

Action<string> log = message => Console.WriteLine(message);

log("Đây là thông điệp qua lambda!");

Ví dụ với Func:

Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 5); // 15

Ví dụ với Predicate:

Predicate<int> isNegative = n => n < 0;

bool test = isNegative(-7); // true

6. Lambda với nhiều biểu thức: khi nào cần block

Nếu lambda phải thực hiện nhiều thao tác, dùng braces và return rõ ràng:

Func<int, int, string> describeSum = (a, b) =>
{
    int sum = a + b;
    return $"Tổng: {sum}";
};

Không có return thì compiler sẽ complain (nhưng thường không giải thích rõ lắm — chỉ báo "not all code paths return a value").

7. Trả về void: Action

Khi lambda không trả gì, dùng Action:

Action greet = () => Console.WriteLine("Cười lên — code đang compile!");

Lambda có thể chứa bao nhiêu câu lệnh tùy thích:

Action<int> printSquare = x =>
{
    int sq = x * x;
    Console.WriteLine($"Bình phương của {x} là {sq}");
};

8. Hạn chế và lỗi thường gặp

Đôi khi muốn viết lambda rất tự do, nhưng compiler không luôn đồng ý.

Không thể khai báo biến có cùng tên với biến bị captured từ bên ngoài.

Cần chú ý kiểu: nếu signature của delegate và lambda không khớp — sẽ lỗi.

Phải trả giá trị nếu delegate yêu cầu return value.

Trong lambda phức tạp nhớ dùng braces. Một biểu thức — không dùng braces và return. Nhiều lệnh — dùng braces và return.

2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Biểu thức lambda với nhiều tham số để cộng số
Biểu thức lambda với nhiều tham số để cộng số
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION