2010-02-02 36 views
31

Tôi đang học C# và tôi thấy LINQ hoàn toàn thú vị. Tuy nhiên những gì boggling tôi là, tôi không thể nghĩ ra một kịch bản theo đó bằng cách sử dụng LINQ sẽ là một trợ giúp to lớn, vì nó thực sự không phải là khó sao chép các tính năng LINQ trong mã.Khi nào tôi nên sử dụng LINQ cho C#?

Bất kỳ trải nghiệm/đề xuất cá nhân nào bạn có thể muốn chia sẻ?

Cảm ơn!

+0

Có bầu chọn để đóng trên cơ sở "chủ quan và tranh luận". Đó là ngu ngốc! Đây là một câu hỏi đơn giản về giá trị duy nhất của LINQ. (Mặt khác, nó chắc chắn là một câu hỏi được sao chép rất nhiều trên SO vì vậy có thể bị đóng vì lý do đó.) –

+0

Tôi sẵn sàng đặt cược chúng là các phiếu "wiki hoặc gần". Đó là chủ quan vì vậy nó có lẽ nên là một câu hỏi wiki. – Greg

+0

Cảm ơn bạn earwicker. Tôi chỉ tò mò, tôi không hiểu tại sao mọi người lại nghĩ đây là một lý do chủ quan. Tôi không biết rằng làm thế nào tôi có thể viết mã trong một tính năng là chủ quan. Cộng đồng những ngày này. Tsk. – nubela

Trả lời

18

Tôi thấy rằng tôi đang sử dụng LINQ bất kỳ lúc nào mà trước đây tôi đã viết một vòng lặp để lấp đầy một vùng chứa. Tôi sử dụng LINQ to SQL như ORM của tôi và rất nhiều LINQ ở khắp mọi nơi khác.

Dưới đây là một đoạn trích nhỏ mà tôi đã viết cho lớp trợ giúp của Active Directory để tìm hiểu xem một người dùng cụ thể có phải là một nhóm cụ thể hay không. Lưu ý việc sử dụng phương thức Any() để lặp qua các nhóm ủy quyền của người dùng cho đến khi nó tìm thấy một với một SID phù hợp. Mã sạch hơn nhiều so với thay thế.

private bool IsInGroup(GroupPrincipal group, UserPrincipal user) 
{ 
    if (group == null || group.Sid == null) 
    { 
     return false; 
    } 
    return user.GetAuthorizationGroups() 
       .Any(g => g.Sid != null && g.Sid.CompareTo(group.Sid) == 0); 
} 

Alternative:

private bool IsInGroup(GroupPrincipal group, UserPrincipal user) 
{ 
    if (group == null || group.Sid == null) 
    { 
     return false; 
    } 
    bool inGroup = false; 
    foreach (var g in user.GetAuthorizationGroups()) 
    { 
     if (g => g.Sid != null && g.Sid.CompareTo(group.Sid) == 0) 
     { 
      inGroup = true; 
      break; 
     } 
    } 
    return inGroup; 
} 

hoặc

private bool IsInGroup(GroupPrincipal group, UserPrincipal user) 
{ 
    if (group == null || group.Sid == null) 
    { 
     return false; 
    } 

    foreach (var g in user.GetAuthorizationGroups()) 
    { 
     if (g => g.Sid != null && g.Sid.CompareTo(group.Sid) == 0) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

Dưới đây là một đoạn mà không tìm kiếm với một kho lưu trữ, đơn hàng và chuyển đổi 10 đối tượng kinh doanh phù hợp đầu tiên vào một cái nhìn cụ thể mô hình (Distance là khoảng cách chỉnh sửa Levenshtein của id duy nhất của mô hình phù hợp từ tham số uniqueID).

model.Results = this.Repository.FindGuestByUniqueID(uniqueID, withExpired) 
           .OrderBy(g => g.Distance) 
           .Take(10) 
           .ToList() 
           .Select(g => new GuestGridModel(g)); 
+2

Thú vị, giải thích về vòng lặp/điền một container? Một số mẫu mã? – nubela

+0

Nói đúng cách điều này không phải là quá nhiều bằng cách sử dụng LINQ vì nó đang sử dụng các phương pháp mở rộng mà cú pháp LINQ chuyển đổi. Tôi chỉ tìm thấy phong cách thông thạo dễ dàng hơn nhiều cho tôi để đọc - ít sự bất hòa nhận thức khi đi qua lại với jQuery. Bạn chắc chắn có thể đại diện cho tất cả các bên trên bằng cách sử dụng cú pháp LINQ là tốt. – tvanfosson

+1

Eh, nếu nó nằm trong không gian tên System.Linq, tôi nghĩ nó được tính là sử dụng LINQ, bất kể bạn gọi nó bằng cú pháp nào. –

12

Tôi thấy LINQ hữu ích khi tôi có bộ sưu tập một số đối tượng và tôi quan tâm đến các mục đáp ứng tiêu chí nhất định. Ví dụ đơn giản sẽ tìm kiếm tất cả các hình dạng trong một tập hợp các hình dạng là hình tròn.

var circles = 
     from s in allShapes 
     where s.Type == ShapeTypes.Circle 
     select s; 

Tôi thừa nhận tôi có thể đã viết một vòng lặp với một số mã trong đó, nhưng tôi thấy mã này ngắn hơn và dễ viết hơn, dễ đọc và dễ hiểu hơn.

LINQ cũng có thể được sử dụng với cơ sở dữ liệu, nhưng tôi thực sự thấy tôi không làm điều đó rất nhiều. Với mỗi người, tôi đoán vậy.

4

Tôi sử dụng LINQ to DataSet rất nhiều để làm việc với DataTables. DataTables là kho dữ liệu chung, nơi tôi thường lưu trữ các giá trị, ví dụ: từ tệp CSV đã tải. Nó dễ đọc hơn và thoải mái hơn khi sử dụng LINQ để truy vấn hoặc nối dữ liệu thay vì "brute-force" -ing với for-loops.

0

Đối với tôi, tôi chỉ sử dụng nó để truy cập cơ sở dữ liệu. Tôi hầu như không bao giờ truy vấn về XML hoặc danh sách.

2

Có, bạn có thể dễ dàng sử dụng LINQ to Objects bằng mã thay thế và không khó. Tôi có xu hướng thích ngữ nghĩa của các biểu thức lambda, và nó quấn một vài dòng mã vào một. Nhưng bạn có thể thực hiện rất nhiều thao tác với mã của riêng mình, ngoại trừ một số thao tác lớn hơn (union, intersect, etc.) dễ dàng hơn với LINQ.

LINQ có các hương vị khác; LINQ to XML làm cho nó thực sự tốt đẹp để làm việc với dữ liệu XML. Tôi thực sự thích nó tốt hơn so với các đối tượng trước đó có sẵn.

LINQ to SQL và ADO.NET Entity Framework (với LINQ to Entities) là một trình ánh xạ quan hệ đối tượng và có thể ánh xạ tới các bảng cơ sở dữ liệu của bạn và hoạt động như các thủ tục được lưu trữ và ADO.NET datasets làm, do đó, đó là một thay thế rất tốt đẹp hơn dữ liệu yếu/datatables, và tôi thích nó hơn mạnh mẽ gõ datasets/bảng quá.

HTH.

+0

Lưu ý vì các đề cập giao cắt/liên kết.Đây cũng là nơi tôi tìm thấy LINQ để có lợi nhất :) Bên cạnh đó, nó thường tài liệu ý định tốt hơn so với vòng lặp foreach. –

0

Tôi thấy hữu ích khi chuyển đổi/dữ liệu "dự án" trước khi liên kết nó với lưới cho mục đích chỉ đọc.

0

Bộ tính năng ngôn ngữ LINQ không thể sao chép dễ dàng như vậy trong mã C# 2.0, không có phương thức mở rộng, biểu thức lambda và thậm chí không có toán tử truy vấn. Toàn bộ điểm LINQ là bạn có một số phiên bản tích hợp của các truy vấn mà bạn sử dụng trình biên dịch để kiểm tra tính chính xác của chúng. Điểm quan trọng khác là sự thống nhất quan điểm tại các nguồn dữ liệu khác nhau, cho dù đó là một cơ sở dữ liệu hoặc trong bộ sưu tập trong bộ nhớ. Bạn có thể sống mà không có LINQ, giống như bạn có thể sống mà không có bất kỳ tính năng nào khác của ngôn ngữ và mã trong Assembler, nhưng có những lợi thế rõ ràng khó giám sát;)

6

Bạn nói đúng, rất hiếm khi tái tạo các tính năng trong C# thông thường. Đó là những gì họ gọi là đường cú pháp. Nó chỉ là về sự tiện lợi. Bạn biết về các thuộc tính tự động? Những cái cho phép bạn viết public class User { public int Id { get; set; } } Đó là cực kỳ dễ sao chép trong mã C# "thông thường". Mặc dù vậy, các thuộc tính tự động vẫn tuyệt vời;)

Lọc và sắp xếp khá nhiều lõi của LINQ. Hãy xem xét bạn có một danh sách người dùng, được gọi là, users và bạn muốn tìm những người đã đăng nhập ngay hôm nay và hiển thị chúng theo thứ tự đăng nhập gần đây nhất. Trước LINQ, bạn có thể làm điều gì đó như tạo danh sách mới, bạn cư trú dựa trên danh sách ban đầu, bằng cách lặp lại nó, thêm những gì đáp ứng các tiêu chí, và sau đó thực hiện một số loại IComparable. Bây giờ bạn chỉ có thể làm:

users = users.Where(u => u.LastLoggedIn.Date = DateTime.Today) 
      .OrderBy(u => u.LastLoggedIn).ToList(); 

Thuận tiện =)

+1

tiện lợi và dễ đọc! –

+1

Và tại sao lại gọi .ToList()? 9 lần trong số 10 nó không cần thiết và nó có thể giết chết hiệu suất của bạn. –

+0

tôi sẽ đồng ý với điều đó, nhưng ví dụ của tôi đã giả định một danh sách người dùng, theo văn bản trước đó. được cấp, tôi có thể dễ dàng thay đổi ví dụ của tôi =) –

10

Cuốn sách Essential LINQ cung cấp một bản tóm tắt một đoạn lớn của lợi ích của LINQ:

LINQ làm nhiều hơn chỉ cần thêm tính năng mới với ngôn ngữ. Nó giới thiệu một phong cách delcarative của lập trình vào ngôn ngữ C#. Mô hình lập trình khai báo cho phép nhà phát triển mã thủ công bắt giữ rõ ràng ý định của họ, mà không buộc họ phải lo lắng về thứ tự diễn ra sự kiện, hoặc triển khai chính xác. Nó cho phép các nhà phát triển nêu rõ những gì họ muốn làm, thay vì làm thế nào nó sẽ được thực hiện .

14

Tùy thuộc vào loại LINQ bạn muốn nói.

Đây có phải là linq-to-sql không? Trong trường hợp đó, đó là một orm với tất cả những lợi ích tương tự đến từ việc sử dụng bất kỳ orm khác. Tôi không sử dụng nhiều và không thể nói nhiều hơn.

Đó có phải là đối tượng không? Trong trường hợp đó, bạn đang thực sự nói về một bộ sưu tập các thứ khác: các phương thức mở rộng, các trình vòng lặp lười và một cú pháp hiểu truy vấn.Đó là giới thiệu về thế giới lập trình hàm. Tôi không có nhiều sử dụng cho cú pháp hiểu truy vấn, nhưng đối với phần còn lại, tôi có thể chứng minh tốt nhất với một ví dụ.

Giả sử bạn muốn đọc từng tệp một. Đối với mỗi dòng, bạn muốn kiểm tra xem nó có đáp ứng một số tiêu chí hay không, hãy chuyển đổi một phần của các dòng đó thành một số nguyên và tổng hợp 10 số nguyên đầu tiên trong số đó cũng nằm trong một phạm vi nhất định. Dưới đây là cách cũ bạn sẽ làm điều đó:

int SumXValues(string filename) 
{ 
    string line; 
    int sum = 0; 
    int count = 0; 
    using (var rdr = new StreamReader(filename)) 
    { 

     while ((line = rdr.ReadLine()) != null && count < 10) 
     { 
      int val; 
      if (int.TryParse(line.Substring(3,3)) 
      { 
       if (val > 4 && val < 25) 
       { 
        sum += val; 
        count ++; 
       } 
      } 
     } 
    } 
    return sum; 
} 

Đây là phương pháp mới:

IEnumerable<string> ReadLines(string filename) 
{ 
    string line; 
    using (var rdr = new StreamReader(filename)) 
     while ((line = rdr.ReadLine()) != null) 
      yield return line; 
} 

int SumXValues(string filename) 
{ 
    return ReadLines(filename) 
       .Select(l => l.Substring(3,3)) 
       .Where(l => int.TryParse(l)) 
       .Select(i => int.Parse(i)) 
       .Where(i => i > 4 && i < 16) 
       .Take(10) 
       .Sum(i => i); 
} 

Thông báo mã mới thực sự là ngắn hơn. Nhưng tại sao nó cũng tốt hơn ? Có (ít nhất) 4 lý do:

  • Hy vọng rằng nó rõ ràng như thế nào lại có thể sử dụng các chức năng readlines là. Bạn cũng có thể đưa ra yếu tố quan trọng hơn, nhưng vấn đề là chỉ ra cách phong cách này giúp bạn sử dụng lại nhiều mã hơn.
  • Tỷ lệ này tốt hơn. Lưu ý tất cả các cuộc gọi hàm chuỗi trong hàm cuối cùng đó. Bạn biết bao nhiêu lần mã sẽ lặp qua các dòng trong tập tin của bạn? Chính xác một lần! Trong thực tế, thậm chí không lâu như nó sẽ ngừng đọc từ tập tin sau khi lấy 10 mục đầu tiên. Và nếu bạn thay đổi nó để trả về một số đếm và sau đó sử dụng ở nơi khác với các phương pháp mở rộng khác? Vẫn chỉ một lần! Điều này cho phép bạn tạo, kết hợp và kết hợp lại kết quả truy vấn của mình khi chạy mà không phải trả thêm chi phí cho các danh sách của bạn.
  • Nó có thể duy trì được nhiều hơn. Nếu các tiêu chí thay đổi, thật dễ dàng để phát hiện chính xác "quy tắc" (nếu bạn muốn) mà bạn quan tâm và sửa đổi phần đó.
  • Dễ đọc hơn. Điều này cho phép bạn thể hiện mã về những gì nó đang làm thay vì nó hoạt động như thế nào.
+0

+! Ví dụ điển hình, lý do chính đáng – Zyphrax

3

Tôi sẽ chuyển câu hỏi xung quanh: bạn có thể chỉ cho chúng tôi cách bạn mô phỏng các tính năng LINQ mà không có nó? Tôi đang gặp sự cố khi nghĩ về trường hợp nó không phải là một trợ giúp to lớn.

Ví dụ, tôi thấy một cái gì đó như thế này thời gian gần đây:

foreach (var person in people.OrderBy(p => p.Company) 
          .ThenBy(p => p.LastName) 
          .ThenBy(p => p.FirstName)) { 
    ... 
} 

Tôi đoán nó có thể đã sử dụng Arrays.Sort, tạo ra một đại biểu rằng kiểm tra các lĩnh vực theo thứ tự đúng, và (ngược từ viết tay, phải không?) sau đó chỉ sống với thực tế là nó sẽ chỉ làm việc trên mảng. Điều đó có vẻ như nó sẽ lâu hơn rất nhiều, khó duy trì hơn và ít linh hoạt hơn.

0

Một điểm nữa để thêm vào tất cả đó là một loại điểm tóm tắt. Bạn có thể thấy ở trên, nó được sử dụng để thuận tiện và gọn gàng và có thể được sử dụng với các bộ sưu tập, SQL, XML (và bất kỳ thứ gì khác quan tâm để triển khai nhà cung cấp LINQ), nhưng tốt nhất bạn chỉ phải tìm hiểu cú pháp LINQ một lần và nó đưa vào tất cả các lĩnh vực công nghệ hữu ích đó.

1

Hãy xem ReSharper nếu bạn chưa có. Nó có rất nhiều gợi ý cho "... chuyển đổi sang cú pháp LINQ" vì vậy nó thường có thể hiển thị cho bạn một hoặc hai điều bạn không cân nhắc khi học. :)

1

Ai đó đã đề cập rằng LINQ là một kiểu lập trình khai báo. Tôi chỉ muốn mở rộng trên đó.

Một cách tôi sử dụng LINQ là viết mã kiểm tra oracle.Điều rất quan trọng là mã thử nghiệm đơn giản và gần với "rõ ràng là chính xác" nhất có thể, nếu không nó sẽ kết thúc với nhiều lỗi như mã mà nó phải thử nghiệm. Với một tính năng cụ thể mà tôi đang thử nghiệm bây giờ, tôi đã viết ra một danh sách nhỏ các thiết lập hiểu được mô tả chính xác cách tôi mong đợi tính năng này hoạt động. Nhờ LINQ, chuyển đổi những comprehensions mã trở nên trivially dễ dàng:

A = all items 
B = [x in A: x.Type = selectedtype, x.Source = "sourceA"] 
C = [x in A: x.Source = "sourceB"] 
D = B union C 

Trong mã:

IEnumerable<MyClass> SetB(IEnumerable<MyClass> allItems, MyType type) 
{ 
    var result = from item in allItems 
       where item.Type == type && item.Source == "sourceA" 
       select item; 
    return result; 
} 

IEnumerable<MyClass> SetC(IEnumerable<MyClass> allItems) 
{ 
    var result = from item in allItems 
       where item.Source == "sourceB" 
       select item; 
    return result; 
} 

IEnumerable<MyClass> SetD(IEnumerable<MyClass> allItems, MyType type) 
{ 
    var setB = SetB(allItems, type); 
    var setC = SetC(allItems); 
    return setB.Union(setC); 
} 

Trong khi vẫn còn khá hơn một chút dài dòng hơn các biểu thức toán học, nó đơn giản hơn nhiều và dễ dàng hơn để gọi là " rõ ràng là chính xác "hơn mã bắt buộc sẽ là. Mã LINQ là khai báo như toán học là khai báo. Ít bản dịch hơn, gần với thông số kỹ thuật hơn. LINQ, khi được sử dụng một cách thích hợp, là một ngôn ngữ "Làm những gì tôi muốn nói".

Lưu ý rằng tôi sẽ không viết mã thực tế theo cách này. Hiệu suất không phải là một yêu cầu cho mã thử nghiệm, nhưng nó là cho mã thực, vì vậy mã thực vẫn cần phải là một thủ tục lưu sẵn SQL.

Các vấn đề liên quan