Series C# hay ho: Lambda Expression

1. Ôn lại khái niệm Delegate

Các bạn vui lòng đọc lại bài trước để nhớ lại các khái niệm về delegate ở đây: Series C# hay ho: Callback trong C# – Delegate, Action, Predicate, Func

Như đã nói ở bài trước, delegate là kiểu dữ liệu để trỏ tới 1 function, do đó khi gán giá trị cho delegate, ta phải gán 1 function vào, như ví dụ dưới đây:

public delegate void TangQuaDelegate(string qua);

public void tangQua(string qua) {
   Console.Write("Da tang " + qua);
}

//Khi sử dụng:
TangQuaDelegate dlg = tangQua;
//Truyền function vào, không phải thực thi function nên ko có dấu ()

2. Anonymous function

Như vậy, mỗi lần muốn truyền 1 function vào delegate, ta phải define function đó, khá phiền phức nhỉ? Trong javascript có anonymous method, viết thẳng function mà ko cần define như sau:

//Dùng anonmyous function, tangQuaDlg giờ đã là 1 delegate
var tangQuaDlg = function(qua) { alert("qua"); };

function oNha(vo, tangQua){
   var qua = "Quà đã nhận";
   tangQua(qua);
}

//Sử dụng trong code
oNha(vo, tangQuaDlg);

May mắn thay, trong C#, ta cũng có thể viết anonymous function theo cách sau (Từ .NET 2.0):


public delegate void TangQuaDelegate(string qua);

TangQuaDelegate dlg =
          delegate(string qua) { Console.WriteLine("Tang quà" + qua); };

Ta thấy viết delegate cách này khá là rườm rà phải không? Microsoft cũng thấy vậy, và họ đã bổ sung lambda expression và .NET 3.0. Muốn biết lambda expression là gì, mới xem phần dưới.

3. Lambda expression

Mình muốn nhắc lại 1 chuyện lần thứ n là: “Các lão developer bên Microsoft rất lười, do đó họ thêm vào C#.NET nhiều thứ, làm developer C#.NET lười theo”. Ta có thể hiểu lambda expression là 1 cách viết anonymous function ngắn gọn hơn:

//Cách cũ
TangQuaDelegate dlg = delegate(string qua) { Console.WriteLine("Tặng quà" + qua); };

//Dùng lambda expression
TangQuaDelegate lamdaDlg = (qua) => { Console.WriteLine("Tặng quà: " + qua); }

//Câu lệnh đầy đủ của lambda expression.
//Dấu "=>" gọi là go-to
(parameters) => { statement }

1

Dưới đây là một số qui tắc viết lambda expression:

//1. Có thể bỏ qua kiểu dữ liệu của parameter truyền vào
(string qua) => {Console.WriteLine("Tặng quà: " + qua);}
(qua) => {Console.WriteLine("Tặng quà: " + qua);}

//2. Nếu không có parameter, bỏ dấu () trống
() => {Console.WriteLine("Hello");}

//3. Nếu chỉ có 1 parameter, có thể bỏ luôn dấu ()
(x) => {Console.WriteLine("Hello " + x);}
x => {Console.WriteLine("Hello " + x);}

//4. Nếu có nhiều parameter, ngăn cách bằng dấu phẩy
(x, y) => {Console.WriteLine("Hello " + x + y);}

//5. Nếu anonymous function chỉ có 1 câu lệnh, có thể bỏ dấu {}
x => { Console.WriteLine("Hello " + x); }
x => Console.WriteLine("Hello " + x)

//6. Nếu chỉ return 1 giá trị, có thể bỏ chữ return.
//4 lambda expression sau tương đương nhau
(x) => { return x > 4; }
x => { return x > 4; }
x => return x > 4
x => x > 4

Tới đây, có bạn sẽ ồ lên kinh ngạc: “À, ra vậy”. Đây là cách ta áp dụng các bước trên để rút gọn 1 lambda expression.

Capture

Cũng có bạn sẽ thắc mắc: Ớ, tưởng lambda expression là gì ghê gớm chứ, hóa ra đơn giản thế thôi à. Vâng, vì nó đơn giản thế nên nhiều bạn sử dụng nó mà không biết tên gọi cũng như chính xác nó là gì.

4. Lambda Expression và LINQ

Đã có bao giờ bạn xem thử param truyền vào cho 1 hàm của LINQ như Where, First là gì chưa?. Vâng, nó chính là 1 delegate cho một function có kiểu trả về là bool (Xem thêm về Func ở bài trước).

Untitled

Do đó, ta sử dụng lambda expression để truyền 1 anonymous function vào hàm Where hoặc First. Ví dụ, khi dùng hàm Where của LINQ để tìm những phần tử trong 1 mảng:

var studentList = new List<Student>();

//Thứ đẹp đẽ ngắn gọn này là lambda expression
var students = studentList.Where(stu => stu.Age > 20);

//Nếu không có nó, ta phải viết cái thứ vừa dài dòng vừa gớm ghiếc như sau
var student = studentList.Where(new delegate(Student stu) { return stu.Age > 20; });

//Hoặc tệ hơn
public bool FindStudentWithAge(Student stu) { return stu.Age > 20; }
var student = studentList.Where(FindStudentWithAge);

Chúc mừng các bạn đã biết được thêm 1 điều hay ho mà ít người biết trong C#.NET. Lambda expression cũng như anonymous function là những vấn đề có tính chuyên sâu trong .NET, có thể bạn sẽ bị hỏi nếu muốn apply vào vị trí senior developer đấy nhé.

Bài viết xin kết thúc ở đây. Hai bài viết tiếp theo sẽ là về Generic và IEnumrable, mong các bạn đón xem.

pr-2

 

14 thoughts on “Series C# hay ho: Lambda Expression”

  1. Quá hay !!!
    Trước đây mình cũng hiểu mấy thứ này nhưng mà hiểu theo kiểu thuộc lòng chứ không có lắp ráp để hiểu cho dễ như vậy.

    Like

  2. Theo mình nghĩ:
    //Nếu không có nó, ta phải viết cái thứ vừa dài dòng vừa gớm ghiếc như sau
    var student = studentList.Where(new delegate(Student stu) { return stu.Age > 20; });

    Cái return này k đúng lắm. vì Where() trả về 1 IENumrable()
    nên nó sẽ phải là:
    var student = studentList.Where(new delegate(Student stu) {
    if(stu.Age > 20)
    yield return stu;
    });

    Có gì sai mong mọi người chỉ giáo. Thansks!

    Like

    1. Func trong Where là để kiểm tra phần tử và trả về true/false, phần tử nào mà Func trả về là true thì sẽ được trả về trong kq của Where, chứ Func trong Where không dùng để trả về đối tượng.

      Like

  3. cái này hay thật anh. Ko biết cái này có được ko? em xài for (int i = 0; i < _myArr.Length; i++) { … } nhiều lần quá, có thể xài cái gì thay cho biểu thức for đó được ko? Nếu có thì nó gọi là gì? Em còn gà lắm có gì xin anh/chị chỉ giáo?

    Like

  4. Mình có một class
    public class Person
    {
    public string Name {get;set;}
    public string Address {get;set;}
    public string Age {get;set;}
    }
    Làm thế nào để mình có thể viết ra một cái Expression như thế này nhỉ
    x=> ( x.Name + x.Address + x.Age).Contains(“gia tri can tim”)

    Like

  5. a ơi cho hỏi từ khóa new ở đây là nhằm mục đích gì vậy ạ
    //Nếu không có nó, ta phải viết cái thứ vừa dài dòng vừa gớm ghiếc như sau
    var student = studentList.Where(new delegate(Student stu) { return stu.Age > 20; });

    Liked by 1 person

Leave a comment