2011-03-01 28 views
8

Tôi thích sử dụng phương pháp mở rộng cho các hoạt động LINQ cơ bản: Where(), Select, nhưng đối phức tạp Select(), SelectMany(), và đặc biệt là OrderBy().ThenBy() báo cáo tôi thấy cú pháp truy vấn để được nhiều dễ đọc hơn và tự nhiên.phần mở rộng LINQ hỗn hợp và truy vấn cú pháp

Hôm nay tôi tìm thấy bản thân mình với các truy vấn sau đây:

from c in _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => 
         c == anotherObject || c.Parent == anotherObject) 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 

Có nguy hiểm (cho dễ đọc, bảo trì, hoặc bất kỳ lý do nào khác) để trộn cú pháp truy vấn và mở rộng?

Điều này có tiềm năng rất chủ quan, nếu có, tôi xin lỗi nếu nó không đáp ứng các yêu cầu cho một câu hỏi chủ quan tốt. Hãy cho tôi biết nếu tôi có thể cải thiện nó!

Trả lời

6

Có nguy hiểm không (để đọc, bảo trì hoặc bất kỳ lý do nào khác) để kết hợp cú pháp truy vấn và tiện ích mở rộng?

Mối nguy hiểm lớn nhất tôi thấy là khả năng bổ sung "bất ngờ" trong mã của bạn, đặc biệt khi được các nhà phát triển khác xem.

Từ quan điểm biên dịch, cú pháp truy vấn được dịch trực tiếp sang các cuộc gọi phương thức mở rộng, do đó, không nhất thiết phải là sự cố kỹ thuật ở đây. Tuy nhiên, điều này có khả năng sẽ bổ sung thêm các cuộc gọi phương thức bổ sung mà sẽ không, ngay từ cái nhìn đầu tiên, được nhiều nhà phát triển mong đợi. Điều này có thể dẫn đến một vấn đề bảo trì tiềm năng.

Điều đó được nói, nếu được thực hiện một cách tiết kiệm và có lý do chính đáng, tôi không cảm thấy có vấn đề thực sự khi trộn cú pháp. Điều này thực sự khá phổ biến - ví dụ, nếu bạn muốn viết cú pháp truy vấn, nhưng cần phải đánh giá đầy đủ, nó thường được bọc trong dấu ngoặc đơn với .ToList() được thêm vào - hoặc nếu bạn muốn sử dụng PLINQ với cú pháp truy vấn, thường là from x in collection.AsParallel() , cũng là cú pháp trộn kỹ thuật ...

+0

Cảm ơn, điều này trực tiếp trả lời hầu hết những suy nghĩ và quan tâm của tôi. – Crisfole

3

Bạn có thể làm điều gì đó như thế này để làm mọi việc dễ dàng hơn một chút.

var firstQuery = _myObject.ObjectsParent.ParentsEnumerable 
       .Where(c => c == anotherObject || c.Parent == anotherObject); 

var secondQuery = from q in firstQuery.MyObjectsEnumerable 
        orderby firstQuery.SortKey, q.Description 
        select new { Item = q, 
           Text = firstQuery.Description + " -> " + q.Description }; 

Bây giờ các truy vấn của bạn không được trộn

+1

Dòng đầu tiên không chính xác ... bạn nên bỏ "từ c trong" ... –

+0

Tôi nghĩ @ Reed-Copsey có nghĩa là (* không nên) vì firstQuery không có Mô tả bất động sản chỉ là một yếu tố của nó. Mã này không hoạt động. – jbtule

1

tôi sử dụng phương pháp khuyến nông, đồng nghiệp của tôi sử dụng cú pháp truy vấn. Không có sự khác biệt.

Tuy nhiên, tôi sẽ nói rằng bạn nên chia nhỏ truy vấn lớn thành truy vấn nhỏ hơn để gỡ lỗi và dễ đọc vì thường không có chi phí thời gian.

1

Tự mình thực hiện việc này (mặc dù không có .Where, nhưng đối với .Cast) Tôi muốn nói nó phụ thuộc rất nhiều vào phương pháp mở rộng mà bạn đang gọi.

ví dụ: Tôi cảm thấy hoàn toàn có quyền sử dụng .Cast vì nó không có sẵn trong đường cú pháp (AFAIK) nhưng có lẽ sẽ tránh. Ở đây, bởi vì nó có một biểu diễn trong cú pháp truy vấn.

Có nói rằng, tôi có thể sử dụng .Chọn để thay đổi dữ liệu trong một truy vấn quá ... Nhưng tôi là một chút của một sadist.

3

Đây là một cuộc gọi phán xét, nhưng nhiều câu hỏi kiểu "thực hành tốt nhất" có xu hướng, ít nhất là lúc đầu. Ý kiến ​​của tôi là bạn nên sử dụng một hoặc cái khác trong một câu lệnh duy nhất. Không thực sự cho bất kỳ "nguy hiểm" vốn có trong pha trộn, nhưng cho rõ ràng.

Trong trường hợp cụ thể này, mệnh đề where rất đơn giản và tôi sẽ cấu trúc lại nó thành cú pháp truy vấn.

Tuy nhiên, các trường hợp không thể được thể hiện rõ ràng trong cú pháp truy vấn. Trong trường hợp không thể tránh khỏi việc trộn cú pháp, các truy vấn sẽ (có thể đọc lại IMO) dễ đọc hơn nếu bạn tách chuỗi phương thức thành biến riêng của nó, sau đó chỉ tham chiếu biến đó trong câu lệnh cú pháp truy vấn. Sử dụng mô hình của bạn làm mô hình:

//The method chain can be pulled out as its own variable... 
var filteredParents = _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => c == anotherObject || c.Parent == anotherObject); 

//...which you can then substitute in a now purely query-syntax statement 
from c in filteredParents 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 
2

Tôi không nghĩ rằng điều đó rất nguy hiểm, có thể đọc được, cú pháp truy vấn rất dễ đọc, nhưng không linh hoạt giá nhỏ phải trả. Tôi đoán câu trả lời là liệu bạn có nghĩ rằng sau đây hoàn toàn bị xích là dễ đọc hơn sau đó những gì bạn đã viết, cá nhân tôi nghĩ rằng bạn dễ đọc hơn.

_myObject.ObjectsParent 
      .ParentsEnumerable 
      .Where(c => c == anotherObject || c.Parent == anotherObject) 
      .SelectMany(c => c.MyObjectsEnumerable, (c, q) => new {c, q}) 
      .OrderBy(t => t.c.SortKey) 
      .ThenBy(t => t.q.Description) 
      .Select(t => new {Item = t.q, Text = t.c.Description + " -> " + t.q.Description}); 
Các vấn đề liên quan