Ngôn ngữ LINQ - Tại sao lại là LINQ?

Tại sao lại là LINQ?

Để hiểu lý do tại sao chúng ta nên sử dụng LINQ, hãy xem xét một số ví dụ sau. Giả sử bạn muốn tìm những sinh viên tuổi từ 13 đến 19 từ một danh sách sinh viên.

Trước C# 2.0, chúng tôi đã phải sử dụng vòng lặp foreach hoặc for duyệt qua danh sách để tìm những sinh viên thỏa điều kiện như dưới đây:

class Student
{
    public int StudentID { get; set; }
    public String StudentName { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Student[] studentArray = 
        { 
            new Student() { StudentID = 1, StudentName = "John", Age = 18 },
            new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 },
            new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
            new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
            new Student() { StudentID = 5, StudentName = "Ron" , Age = 31 },
            new Student() { StudentID = 6, StudentName = "Chris",  Age = 17 },
            new Student() { StudentID = 7, StudentName = "Rob",Age = 19  },
        };

        var students = new List<Student>();
        foreach (Student student in studentArray)
        {
            if (student.Age > 12 && student.Age < 20)
            {
                students.Add(student);
            }
        }
    }
}

Sử dụng vòng lặp foreachfor khá là cồng kềnh, khó bảo trì và khó đọc. Delegate được giới thiệu từ C# 2.0, có thể được sử dụng để giải quyết loại kịch bản này, như được trình bày dưới đây:

delegate bool FindStudent(Student student);

class StudentExtension
{ 
    public static List<Student> Where(Student[] stdArray, FindStudent findStudent)
    {
        List<Student> result = new List<Student>();
        foreach (Student student in stdArray)
        {
            if (findStudent(student))
            {
                result.Add(student);
            }
        }        
        return result;
    }
}
    
class Program
{
    static void Main(string[] args)
    {
        Student[] studentArray = 
        { 
            new Student() { StudentID = 1, StudentName = "John", Age = 18 },
            new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 },
            new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
            new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
            new Student() { StudentID = 5, StudentName = "Ron" , Age = 31 },
            new Student() { StudentID = 6, StudentName = "Chris",  Age = 17 },
            new Student() { StudentID = 7, StudentName = "Rob",Age = 19  },
        };

        var students = StudentExtension.Where(studentArray, delegate(Student student) 
        {
            return student.Age > 12 && student.Age < 20;
        });
    }
}

Vì vậy, với ưu điểm của delegate bạn có thể tìm kiếm sinh viên với bất kỳ tiêu chí nào. Bạn không phải viết lại các vòng lặp foreach hoặc for để tìm sinh viên sử dụng các tiêu chí khác nhau.

Ví dụ: bạn có thể sử dụng cùng chức năng delegate để tìm một sinh viên có StudentId là 5 hoặc tên là Bill, như sau:

var students = StudentExtension.Where(studentArray, delegate(Student std) {
    return std.StudentID == 5;
});

//Also, use another criteria using same delegate
var students = StudentExtension.Where(studentArray, delegate(Student std) {
    return std.StudentName == "Bill";
});

Nhóm phát triển C# cảm thấy rằng họ vẫn cần làm cho mã nhỏ gọn và dễ đọc hơn. Vì vậy, họ đã giới thiệu phương thức mở rộng, biểu thức lambda, cây biểu thức, kiểu ẩn danh và biểu thức truy vấn trong C# 3.0.

Bạn có thể sử dụng các tính năng này của C# 3.0, chúng là các khối thành phần tạo nên LINQ. Chúng có thể được sử dụng để truy vấn các loại danh sách khác nhau và nhận kết quả trả về trong một câu lệnh.

Ví dụ dưới đây cho thấy cách bạn có thể sử dụng truy vấn LINQ với biểu thức lambda để tìm sinh viên như ví dụ ở bên trên.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoLinq
{
   class Student
	{
		public int StudentID { get; set; }
		public String StudentName { get; set; }
		public int Age { get; set; }
	}

    class Program
    {
        static void Main(string[] args)
        {
            Student[] studentArray = 
        { 
            new Student() { StudentID = 1, StudentName = "John", Age = 18 },
            new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 },
            new Student() { StudentID = 3, StudentName = "Bill",  Age = 25 },
            new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 },
            new Student() { StudentID = 5, StudentName = "Ron" , Age = 31 },
            new Student() { StudentID = 6, StudentName = "Chris",  Age = 17 },
            new Student() { StudentID = 7, StudentName = "Rob",	Age = 19  },
        };

        // Use LINQ to find teenager students
        var teenAgerStudents = studentArray.Where(s => s.Age > 12 && s.Age < 20).ToList();
       	foreach(var st in teenAgerStudents)
			 Console.WriteLine(st.StudentName);
        // Use LINQ to find first student whose name is Bill 
        var bill = studentArray.Where(s => s.StudentName == "Bill").FirstOrDefault();
         	 Console.WriteLine("Tuoi cua Bill la:"+bill.Age);
        // Use LINQ to find student whose StudentID is 5
        var student5 = studentArray.Where(s => s.StudentID == 5).FirstOrDefault();		
                Console.WriteLine("Tuoi cua Ron la:"+student5.Age);

        Console.ReadLine();
		}
    }
     
}

Xem ví dụ

Như bạn có thể thấy trong ví dụ trên, chúng tôi chỉ định các tiêu chí khác nhau bằng cách sử dụng toán tử LINQ và biểu thức lambda trong một câu lệnh.

Do đó, LINQ làm cho mã nhỏ gọn hơn và dễ đọc hơn và nó cũng có thể được sử dụng để truy vấn các nguồn dữ liệu khác nhau.

Ví dụ: nếu bạn có một bảng sinh viên trong cơ sở dữ liệu thay vì một mảng các đối tượng sinh viên như trên, bạn vẫn có thể sử dụng cùng một truy vấn để tìm sinh viên bằng cách sử dụng Entity Framework.

Ưu điểm của LINQ

  • Ngôn ngữ quen thuộc: Nhà phát triển không phải học ngôn ngữ truy vấn mới cho từng loại nguồn dữ liệu hoặc định dạng dữ liệu.
  • Viết ít code: Nó làm giảm số lượng mã được viết so với cách tiếp cận truyền thống hơn.
  • Code dễ đọc: LINQ làm cho mã dễ đọc hơn để các nhà phát triển khác có thể dễ dàng hiểu và bảo trì nó.
  • Cách truy vấn chuẩn hóa nhiều nguồn dữ liệu: Có thể sử dụng cùng một cú pháp LINQ để truy vấn nhiều nguồn dữ liệu.
  • An toàn khi biên dịch của các truy vấn: Nó cung cấp kiểm tra kiểu của các đối tượng tại thời gian biên dịch.
  • Hỗ trợ IntelliSense: LINQ cung cấp IntelliSense cho các danh sách kiểu generic.
  • Định hình dữ liệu: Bạn có thể truy xuất dữ liệu theo các hình dạng khác nhau.