quang cao hosting

SERIES C# hay : LINQ lột mặt na của Linq

Xem: 376    Tải: 0   Thảo luận: 0   Mục: C / C++ / MFC   Lĩnh vực: Khác

8 điểm   ( 2 đánh giá ) File đã được kiểm thử

1. LINQ có thực sự dễ như ta tưởng?

LINQ không phải là 1 khái niệm xa lạ đối với các C#.NET developer, nhất là những bạn hay làm việc với database (LINQ to SQL). Tuy nhiên, đa phần trong chúng ta đều sử dụng LINQ mà không biết rõ nó hoạt động như thế nào. Chắc ai cũng từng viết những dòng code như sau:

public class Student
 {
    public string Name { get; set; }
    public int Age { get; set; }
 }
var students = new List<Student>();
var result = students.Where(stu => stu.Age < 20);

Dòng code rất dễ hiểu, lọc ra những học sinh có số tuổi < 20. Tuy nhiên, liệu bạn có trả lời được những câu hỏi sau:

  1. Dấu “=>” là dấu gì. Toàn bộ cụm “stu => stu.Age < 20” được gọi là gì?
  2. Hàm Where được viết như thế nào, nhận parameter gì vào, trả ra giá trị gì?
  3. Tại sao IDE tại biết stu là 1 Student để có thể nhắc lệnh?
  4. Có thể viết 1 thứ tương tự như LINQ trong javascript không?

Nếu bạn chỉ trả lời đc 1,2 hoặc không trả lời đc câu hỏi nào, bạn chưa thực sự hiểu LINQ. Đừng lo, ngày xưa mình cũng thế. Bài viết này sẽ giúp bạn giải đáp những câu hỏi trên, cũng như hiểu rõ hơn về LINQ. (Đáp án ở cuối bài viết).

2. Ôn lại kiến thức

LINQ được implement bằng cách tổng hợp khá nhiều khái niệm hay ho và phức tạp của ngôn ngữ C#. Nếu bạn nào thường xuyên theo dõi blog, đã đọc những bài viết trước thì chắc là biết rồi. Với các bạn chưa biết, những khái niệm đó bao gồm:

3. Cùng “lột mặt nạ” LINQ

Để sử dụng LINQ, chúng ta phải dùng namespace System.Linq. Thật ra Linq là 1 danh sách các extension method, thêm một số method cho interface IENumerable. Vì các class List, DbSet, … đều implement interface này, do đó chúng đều có thể gọi Linq method.

Đây là signature của 3 Linq method cơ bản: Where, Select và First.

public static class Enumerable
 {
   public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
   public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);
   public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
}

Có bạn sẽ ngạc nhiên: Cái đống xấu xí gớm ghiếc khó hiểu này chính là Linq xinh đẹp của mình sao? Vâng, ngày xưa sau khi xem bạn gái tẩy trang xong mình cũng có cảm giác như các bạn vậy =)))

Trong phạm vi bài viết, mình chỉ giải thích method Where, các bạn có thể dựa vào đó để tự tìm hiểu thêm. Ta thấy method nhận vào 1 object có kiểu Func<TSource, bool> (link), có a thấy quen ko? Đây là 1 delegate (con trỏ hàm), trỏ tới 1 method có params là TSource, kiểu trả về là bool. TSource ở đây là kiểu dữ liệu generic, do đó ta có thể khai báo kiểu gì cũng được.

Nếu bạn chưa rành lắm về generic, hãy xem kiểu TSource như kiểu Student, signature của hàm Where sẽ thành:

public static IEnumerable<Student> Where<Student>(this IEnumerable<Student> source, Func<Student, bool> predicate);

Mình sẽ viết lại method Linq ở đầu bài, từ phức tạp đến đơn giản. Mình không dùng var để các bạn hiểu rõ kiểu dữ liệu đưa vào và trả về:

//Gán method vào delegate
public bool FindStudent(Student stu) { return stu.Age &amp;amp;lt; 20; }
 
//Sử dụng lambda expression sẽ ngắn hơn
//Xem lại bài viết về lamda expression
Func<Student, bool> func1 = FindStudent;
func1 = stu => stu.Age < 20;
 
List<Student> students = new List<Student>();
IEnumerable<Student> result = students.Where<Student>(func1);
 
//Với generic trong C#, ta không cần nói rõ kiểu dữ liệu.
//Dựa vào kiểu dữ liệu của Func&amp;amp;lt;Student, bool&amp;amp;gt; truyền vào
//C# tự hiểu ta dùng hàm Where với kiểu dữ liệu Student
 
//Ta bỏ kiểu Student, thay func bằng lambda
var result = students.Where(stu => stu.Age < 20);

4. Tự viết LINQ

Đến đây, chúng ta có thể tự viết 1 Linq method . Mọi chuyện rất đơn giản, bạn chỉ cần viết 1 extension method cho IENumerable, với signature tương tự như Linq. Đây là method Linq do mình viết

public static class MyLinq
{
  //Extension method
  public static IEnumerable<TSource> MyWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
  {
    //Loop toàn bộ cái item trong danh sách truyền vào
    foreach (var item in source)
    {
      // Callback lại hàm đã truyền vào, hàm này trả giá trị boolean
      // Nếu hàm callback return true, đưa item đó vào IENumerable kết quả
      // Xem lại vài IEnumerable và yield
      if (predicate(item))  yield return item;
    }
  }
}

Method này khá đơn giản, vì mình đã bỏ qua các bước check null v…v, tuy nhiên nó cho kết quả tương tự như method Where trong Linq.

var result = students.MyWhere(stu => stu.Age < 20);

Tới đây, mình sẽ trả lời 4 câu hỏi đã nêu ra ở đầu bài.

  1. Dấu “=>” là dấu gì. Toàn bộ cụm “stu => stu.Age < 20” được gọi là gì? Dấu “=>” là dấu “go-to”, toàn bộ cụm đi kèm là 1 lambda expression. Bản chất của lambda expression là 1 anonymous method.
  2. Hàm Where được viết như thế nào, nhận parameter gì vào, trả ra giá trị gì? Hàm Where là 1 extension method của class IEnumerable, nhận vào 1 delegate với kiểu trả về là bool, trả ra 1 IEnumerable đã filter.
  3. Tại sao IDE tại biết stu là 1 Student để có thể nhắc lệnh? Ở đây ta sử dụng lambda expression, stu là 1 param của hàm. Do Linq sử dụng generic, list students là 1 list với kiểu dữ liệu Student. do đó C# tự hiểu stu là 1 param với kiểu dữ liệu Student.
  4. Có thể viết 1 thứ tương tự như LINQ trong javascript không? Có thể. Bạn có thể tìm hiểu thêm về underscore và lodash, 2 thư viện hỗ trợ linq cho javascript.

Bài viết kết thúc ở đây. Bạn nào muốn tìm hiểu chuyên sâu hơn có thể tìm đọc C# in Depth. 70% kiến thức mình có được về LINQ và cái khái niệm trên là nhờ đọc cuốn này .Vì LINQ là 1 chủ đề khá phức tạp, cần giải thích nhiều, nếu bạn nào còn thắc mắc có thể để lại comment hoặc gửi mail cho mình nhé.

SERIES C# hay : LINQ lột mặt na của Linq

SERIES C# hay : LINQ lột mặt na của Linq Đăng ngày 16-08-2016  LINQ không phải là 1 khái niệm xa lạ đối với các C#.NET developer, nhất là những bạn hay làm việc với database (LINQ to SQL). Tuy nhiên, đa phần trong chúng ta đều sử dụng LINQ mà không biết rõ nó hoạt động như thế nào. 4/10 376

Thảo luận:

Để bình luận bạn phải đăng nhập thành viên.

File tương tự

Files cùng mục

 
Hỗ trợ kỹ thuật cho thành viên:
Số di động (Hotline): 085.99999.25
Thời gian làm việc:
Sáng: 8h-12h; Chiều: 13h30-17h30
(Nghỉ chiều T7, CN và các ngày lễ, tết)
Chat với Megacode
https://www.facebook.com/megacodevn
File gợi ý cho bạn
File tải nhiều nhất
Megacode.vn - Thư viện mã nguồn chia sẻ, tải file cho cộng đồng
Copyright © 2013-2016. All rights reserved. Bản quyền thuộc VinaGon
Địa chỉ: Số 38 Hàng Bè, Hàng Bạc, Hoàn Kiếm, Hà Nội.
Văn phòng giao dịch: Phòng 28, Tầng 6, HH1A Linh Đàm, Hoàng Mai, Hà Nội
Email: info@vinagon.com | Website: www.vinagon.com | Điện thoại: 085.99999.25;