Tên tham số phản ánh: lạm dụng biểu thức C # lambda hoặc sáng chói Cú pháp?


428

Tôi đang xem thành phần MvcContrib Grid và tôi bị mê hoặc, nhưng đồng thời bị đẩy lùi, bởi một thủ thuật cú pháp được sử dụng trong cú pháp Grid :

.Attributes(style => "width:100%")

Cú pháp trên đặt thuộc tính kiểu của HTML được tạo thành width:100%. Bây giờ nếu bạn chú ý, 'style' không được chỉ định, được suy ra từ tên của tham số trong biểu thức! Tôi đã phải đào sâu vào vấn đề này và tìm thấy nơi 'phép thuật' xảy ra:

Hash(params Func<object, TValue>[] hash)
{
    foreach (var func in hash)
    {
        Add(func.Method.GetParameters()[0].Name, func(null));
    }
}

Vì vậy, thực sự, mã đang sử dụng thời gian chính thức, biên dịch, tên của các tham số để tạo từ điển của các cặp tên-giá trị thuộc tính. Cấu trúc cú pháp kết quả thực sự rất biểu cảm, nhưng đồng thời rất nguy hiểm. Việc sử dụng chung các biểu thức lambda cho phép thay thế các tên được sử dụng mà không có tác dụng phụ. Tôi thấy một ví dụ trong một cuốn sách nói rằng collection.ForEach(book => Fire.Burn(book))tôi biết tôi có thể viết mã của mình collection.ForEach(log => Fire.Burn(log))nó có nghĩa tương tự . Nhưng với cú pháp MvcContrib Grid ở đây đột nhiên, tôi tìm thấy mã chủ động xem xét và đưa ra quyết định dựa trên tên tôi chọn cho các biến của mình!

Vì vậy, đây có phải là thông lệ chung với cộng đồng C # 3.5 / 4.0 và những người yêu thích biểu thức lambda? Hay là một mánh khóe lừa đảo mà tôi không nên lo lắng?


34
Tôi sẽ lập luận rằng điều này có vẻ rõ ràng, miễn là bạn sẵn sàng xem xét ý định của mã, thay vì chỉ phân tích cú pháp. Mà, nếu bạn đang đọc mã tốt, dù sao thì bạn cũng nên làm. Cú pháp chỉ là một phương tiện cho ý định, và tôi sẽ cho rằng đây là ý định tiết lộ mã.
Jamie Penney

190
Tôi chỉ hỏi Anders (và phần còn lại của nhóm thiết kế) họ nghĩ gì. Hãy nói rằng kết quả sẽ không được in trên một tờ báo thân thiện với gia đình.
Eric Lippert

22
C # hiện đang thiếu một cú pháp nhẹ, rõ ràng cho các bản đồ, đặc biệt là các bản đồ được truyền vào các chức năng. Các ngôn ngữ động khác nhau (Ruby, Python, JavaScript, ColdFusion 9) có cú pháp rõ ràng, nhẹ nhàng cho một số mở rộng hoặc khác.
yfeldblum

28
Ồ, tôi nghĩ rằng nó rất thú vị. Đối với một cú pháp cho bản đồ, vâng, thật tuyệt nếu chúng ta có thể làm {{"Do", "Một con nai"}, {"Re", "mặt trời vàng"} ... và trình biên dịch suy ra xây dựng bản đồ, giống như mới [] {1, 2,3} xâm nhập vào việc xây dựng một mảng int. Chúng tôi đang xem xét những thứ này.
Eric Lippert

17
Eric Lippert, tôi rất tôn trọng bạn, nhưng tôi nghĩ rằng bạn và nhóm (bao gồm cả Anders, người mà tôi tôn trọng FREAKIN 'TREMENDOUSLY) đang đánh đập điều này quá gay gắt. Như bạn thừa nhận, C # thiếu một cú pháp chặt chẽ cho bản đồ và một số lang khác (như Ruby) có những cú pháp tuyệt vời. Anh chàng này đã tìm ra cách để có được cú pháp mình muốn. Tôi sẽ cấp cho bạn một số cách tương tự để diễn đạt nó gần như biểu cảm như cú pháp của anh ấy với ít nhược điểm hơn. Nhưng cú pháp của anh ấy và thực tế anh ấy đã làm việc rất chăm chỉ để có được nó rõ ràng cho thấy sự cần thiết phải cải thiện ngôn ngữ. Hiệu suất trong quá khứ cho thấy các bạn sẽ tạo ra một cái gì đó tuyệt vời cho nó.
Charlie Hoa

Câu trả lời:


147

Điều này có interop nghèo. Ví dụ, hãy xem xét ví dụ C # - F # này

C #:

public class Class1
{
    public static void Foo(Func<object, string> f)
    {
        Console.WriteLine(f.Method.GetParameters()[0].Name);
    }
}

F #:

Class1.Foo(fun yadda -> "hello")

Kết quả:

"arg" được in (không phải "yadda").

Do đó, các nhà thiết kế thư viện nên tránh các loại 'lạm dụng' này, hoặc ít nhất là cung cấp quá tải 'tiêu chuẩn' (ví dụ: lấy tên chuỗi làm tham số phụ) nếu họ muốn có sự giao thoa tốt giữa các ngôn ngữ .Net.


11
Bạn không. Chiến lược này chỉ đơn giản là không di động. (Trong trường hợp nó giúp, ví dụ như cách khác, F # có thể có khả năng nạp chồng các phương thức chỉ khác nhau về kiểu trả về (suy luận kiểu có thể làm điều đó). Điều này có thể được thể hiện trong CLR. Nhưng F # không cho phép bạn đã làm điều đó, các API đó sẽ không thể gọi được từ C #.) Khi nói đến việc xen kẽ, luôn có sự đánh đổi ở các tính năng 'cạnh' liên quan đến lợi ích bạn nhận được so với những gì bạn giao dịch.
Brian

32
Tôi không thích khả năng không tương tác là một lý do để không làm điều gì đó. Nếu khả năng tương tác là một yêu cầu thì hãy làm nó, nếu không, thì tại sao phải lo lắng về nó? Đây là YAGNI IMHO.
John Farrell

15
@jfar: Trong .NET CLR, khả năng tương tác đất có một độ mờ hoàn toàn mới, vì các tập hợp được tạo trong bất kỳ trình biên dịch nào được cho là được sử dụng từ bất kỳ ngôn ngữ nào khác .
Remus Rusanu

25
Tôi đồng ý rằng bạn không cần phải tuân thủ CLS, nhưng có vẻ là một ý tưởng tốt nếu bạn đang viết thư viện hoặc điều khiển (và đoạn trích bắt đầu từ lưới này, vâng?) Nếu không, bạn chỉ đang giới hạn đối tượng / cơ sở khách hàng của bạn
JMarsch

4
Có lẽ nên thay đổi: Func <object, string> thành Expression << Func <object, string >> Và nếu bạn buộc bên phải của biểu thức thành hằng số, bạn có thể có một triển khai thực hiện điều này: IDadata tĩnh công khai <chuỗi, chuỗi> Hash (Biểu thức params <Func <object, chuỗi >> [] hash) {Dictionary <string, string> value = new Dictionary <string, string> (); foreach (var func in hash) {value [func.Parameter [0] .Name] = (chuỗi) ((ConstantExpression) func.Body) .Value; } giá trị trả về; }
davidfowl

154

Tôi thấy kỳ lạ không phải vì cái tên , mà vì lambda là không cần thiết ; nó có thể sử dụng loại ẩn danh và linh hoạt hơn:

.Attributes(new { style = "width:100%", @class="foo", blip=123 });

Đây là một mẫu được sử dụng trong phần lớn ASP.NET MVC (ví dụ) và có các cách sử dụng khác (một lời cảnh báo , cũng lưu ý suy nghĩ của Ayende nếu tên đó là một giá trị ma thuật thay vì cụ thể của người gọi)


4
Điều này cũng có vấn đề interop; không phải tất cả các ngôn ngữ đều hỗ trợ tạo ra một loại ẩn danh như thế một cách nhanh chóng.
Brian

5
Tôi thích cách không ai thực sự trả lời câu hỏi, thay vào đó mọi người đưa ra một lập luận "điều này tốt hơn". : p Có phải là lạm dụng hay không?
Sam Saffron

7
Tôi rất thích thú khi thấy phản ứng của Eric Lippert về điều này. Bởi vì đó là mã FRAMEWORK . Và nó thật kinh khủng.
Matt Hinze

26
Tôi không nghĩ vấn đề là dễ đọc sau khi mã được viết. Tôi nghĩ vấn đề thực sự là khả năng học hỏi của mã. Bạn sẽ nghĩ gì khi intellisense của bạn nói .Attribution (object obj) ? Bạn sẽ phải đọc tài liệu (điều mà không ai muốn làm) bởi vì bạn sẽ không biết phải truyền gì cho phương thức này. Tôi không nghĩ rằng điều này thực sự tốt hơn ví dụ trong câu hỏi.
NotDan

2
@Arni - tại sao linh hoạt hơn: nó không dựa vào tên tham số ngụ ý, điều này có thể (không trích dẫn tôi) gây ra vấn đề với một số triển khai lambda (ngôn ngữ khác) - nhưng bạn cũng có thể sử dụng các đối tượng thông thường với các thuộc tính được xác định. Ví dụ: bạn có thể có một HtmlAttributeslớp với các thuộc tính dự kiến ​​(đối với intellisense) và chỉ cần bỏ qua các thuộc tính có nullgiá trị ...
Marc Gravell

137

Tôi chỉ muốn đưa ra ý kiến ​​của tôi (Tôi là tác giả của thành phần lưới MvcContrib).

Đây chắc chắn là lạm dụng ngôn ngữ - không nghi ngờ gì về nó. Tuy nhiên, tôi sẽ không thực sự coi nó phản tác dụng trực quan - khi bạn nhìn vào một cuộc gọi đến Attributes(style => "width:100%", @class => "foo")
tôi nghĩ nó khá rõ ràng những gì đang diễn ra (Nó chắc chắn không tệ hơn cách tiếp cận kiểu ẩn danh). Từ góc độ intellisense, tôi đồng ý rằng nó khá mờ.

Đối với những người quan tâm, một số thông tin cơ bản về việc sử dụng nó trong MvcContrib ...

Tôi đã thêm nó vào lưới theo sở thích cá nhân - Tôi không thích sử dụng các loại ẩn danh làm từ điển (có một tham số lấy "đối tượng" cũng mờ đục như một tham số Func []) và trình khởi tạo bộ sưu tập Từ điển là khá dài dòng (Tôi cũng không phải là fan hâm mộ của giao diện lưu loát dài dòng, ví dụ: phải liên kết nhiều cuộc gọi đến một Thuộc tính ("kiểu", "hiển thị: không"). Thuộc tính ("lớp", "foo"), v.v.)

Nếu C # có cú pháp dài dòng hơn cho các từ điển, thì tôi sẽ không bận tâm đến việc bao gồm cú pháp này trong thành phần lưới :)

Tôi cũng muốn chỉ ra rằng việc sử dụng điều này trong MvcContrib là hoàn toàn tùy chọn - đây là những phương thức mở rộng bao bọc quá tải mà thay vào đó là một IDadata. Tôi nghĩ điều quan trọng là nếu bạn cung cấp một phương pháp như thế này, bạn cũng nên hỗ trợ một cách tiếp cận 'bình thường' hơn, ví dụ như để giao tiếp với các ngôn ngữ khác.

Ngoài ra, một người nào đó đã đề cập đến 'chi phí phản chiếu' và tôi chỉ muốn chỉ ra rằng thực sự không có quá nhiều chi phí với phương pháp này - không có phản ánh thời gian chạy hoặc biên dịch biểu thức liên quan (xem http://blog.bittercoder.com /PermaLink,guid, 206e64d1-29ae-4362-874b-83f5b103727f.aspx ).


1
Tôi cũng đã cố gắng giải quyết một số vấn đề được nêu ở đây sâu hơn trên blog của mình: jeremyskinner.co.uk/2009/12/02/lambda-abuse-the-mvccontrib-hash
Jeremy Skinner

4
Nó không kém phần mờ đục trong Intellisense so với các đối tượng ẩn danh.
Brad Wilson

22
+1 để đề cập rằng giao diện được thêm thông qua các phương thức mở rộng tùy chọn . Người dùng không C # (và bất kỳ ai bị xúc phạm bởi lạm dụng ngôn ngữ) chỉ có thể kiềm chế sử dụng nó.
Jørn Schou-Rode

50

Tôi thích

Attributes.Add(string name, string value);

Nó rõ ràng và chuẩn hơn nhiều và không có gì đạt được bằng cách sử dụng lambdas.


20
Có phải mặc dù? html.Attributes.Add("style", "width:100%");không đọc độc đáo như style = "width:100%"(html thực tế được tạo), trong khi style => "width:100%"rất gần với giao diện của HTML.
Jamie Penney

6
Cú pháp của họ cho phép các thủ thuật như .Attribution (id => 'foo', @group => 'bar', style => 'width: 100%'). Chữ ký hàm sử dụng cú pháp params cho số lượng biến args: Attribution (params Func <object, object> [] args). Nó rất mạnh mẽ, nhưng tôi đã mất khá nhiều thời gian để hiểu wtf.
Remus Rusanu

27
@Jamie: Cố gắng làm cho mã C # trông giống như mã HTML sẽ là một lý do tồi cho các mô tả thiết kế. Chúng là những ngôn ngữ hoàn toàn khác nhau cho các mục đích hoàn toàn khác nhau và chúng không nên giống nhau.
Guffa

17
Một vật thể ẩn danh cũng có thể đã được sử dụng, mà không làm mất đi "vẻ đẹp"? .Attribution (new {id = "foo", @group = "bar", style = "width: 100%"}) ??
Funka

10
@Guffa Tại sao nó là một lý do xấu cho các quyết định thiết kế? Tại sao chúng không giống nhau? Bởi lý do đó họ nên cố ý nhìn khác nhau? Tôi không nói sai của bạn, tôi chỉ nói rằng bạn có thể muốn nói rõ hơn về quan điểm của bạn.
Samantha Branham

45

Chào mừng đến với Rails Land :)

Thực sự không có gì sai với nó miễn là bạn biết chuyện gì đang xảy ra. (Đó là khi loại điều này không được ghi nhận tốt rằng có vấn đề).

Toàn bộ khung Rails được xây dựng trên ý tưởng quy ước về cấu hình. Đặt tên mọi thứ theo một cách nhất định sẽ đưa bạn vào một quy ước mà họ đang sử dụng và bạn có được rất nhiều chức năng miễn phí. Theo quy ước đặt tên sẽ đưa bạn đến nơi bạn sẽ đến nhanh hơn. Toàn bộ hoạt động rực rỡ.

Một nơi khác mà tôi đã thấy một mẹo như thế này là trong các xác nhận cuộc gọi phương thức trong Moq. Bạn vượt qua trong lambda, nhưng lambda không bao giờ bị xử tử. Họ chỉ sử dụng biểu thức để đảm bảo rằng cuộc gọi phương thức đã xảy ra và ném ngoại lệ nếu không.


3
Tôi hơi do dự, nhưng tôi đồng ý. Ngoài chi phí phản ánh, không có sự khác biệt đáng kể giữa việc sử dụng một chuỗi như trong Thêm () so với sử dụng tên tham số lambda. Ít nhất là tôi có thể nghĩ ra. Bạn có thể muck nó lên và gõ "tinh tế" mà không nhận thấy cả hai cách.
Samantha Branham

5
Tôi không thể hiểu tại sao điều này không lạ với tôi, và rồi tôi nhớ Rails. : D
Allyn

43

Điều này là khủng khiếp trên nhiều cấp độ. Và không, điều này không giống với Ruby. Đó là sự lạm dụng C # và .Net.

Đã có nhiều gợi ý về cách thực hiện điều này theo cách thẳng thắn hơn: bộ dữ liệu, loại ẩn danh, giao diện lưu loát, v.v.

Điều làm cho nó trở nên tồi tệ là cách duy nhất để ưa thích cho chính nó:

  • Điều gì xảy ra khi bạn cần gọi nó từ VB?

    .Attributes(Function(style) "width:100%")

  • Nó hoàn toàn phản trực quan, intellisense sẽ cung cấp ít trợ giúp để tìm ra làm thế nào để vượt qua mọi thứ.

  • Nó không cần thiết không hiệu quả.

  • Không ai sẽ có bất kỳ manh mối làm thế nào để duy trì nó.

  • Kiểu của đối số đi vào thuộc tính là Func<object,string>gì? Làm thế nào là ý định tiết lộ. Tài liệu intellisense của bạn sẽ nói gì, "Vui lòng bỏ qua tất cả các giá trị của đối tượng"

Tôi nghĩ rằng bạn hoàn toàn hợp lý khi có những cảm giác hồi sinh.


4
Tôi muốn nói - nó hoàn toàn trực quan. :)
Arnis Lapsa

4
Bạn nói nó không giống Ruby. Nhưng đó là một cú hích khủng khiếp giống như cú pháp của Ruby để chỉ định các khóa và giá trị của hàm băm.
Charlie Hoa

3
Mã phá vỡ theo chuyển đổi alpha! Yey!
Phil

3
@Charlie, về mặt cú pháp có vẻ tương tự nhau, về mặt ngữ nghĩa thì khác.
Sam Saffron

39

Tôi đang ở trong trại "cú pháp sáng chói", nếu họ ghi chép lại rõ ràng, và nó trông thật tuyệt vời, gần như không có vấn đề gì với nó cả!


10
Amen, anh trai. Amen (Amen thứ 2 cần phải đáp ứng thời lượng tối thiểu để nhận xét :)
Charlie Hoa

Nhận xét của bạn là cách nhiều hơn cần thiết. Nhưng sau đó, bạn không thể chỉ Amen một lần và sau đó đưa vào nhận xét của mình: D
ngủ say Smith

37

Cả hai. Đó là lạm dụng các biểu thức lambda sáng chói cú pháp.


16
Vì vậy, đó là một lạm dụng cú pháp tuyệt vời của biểu thức lambda? Tôi nghĩ tôi đồng ý :)
Seth Petry-Johnson

21

Tôi hầu như không bao giờ gặp loại sử dụng này. Tôi nghĩ nó "không phù hợp" :)

Đây không phải là một cách sử dụng phổ biến, nó không phù hợp với các quy ước chung. Tất nhiên loại cú pháp này có ưu và nhược điểm:

Nhược điểm

  • Mã này không trực quan (các quy ước thông thường là khác nhau)
  • Nó có xu hướng dễ vỡ (đổi tên tham số sẽ phá vỡ chức năng).
  • Khó kiểm tra hơn một chút (giả mạo API sẽ yêu cầu sử dụng phản xạ trong các thử nghiệm).
  • Nếu biểu thức được sử dụng mạnh mẽ, nó sẽ chậm hơn do nhu cầu phân tích tham số chứ không chỉ giá trị (chi phí phản ánh)

Ưu

  • Nó dễ đọc hơn sau khi nhà phát triển điều chỉnh cú pháp này.

Điểm mấu chốt - trong thiết kế API công cộng tôi đã chọn cách rõ ràng hơn.


2
@Elisha - Ưu và nhược điểm của bạn bị đảo ngược. Ít nhất tôi hy vọng bạn không nói rằng một Pro có mã "không trực quan". ;-)
Metro Smurf

Đối với trường hợp cụ thể này - tên tham số lambda và tham số chuỗi đều dễ vỡ. Giống như sử dụng động để phân tích cú pháp xml - điều đó phù hợp vì dù sao bạn cũng không thể chắc chắn về xml.
Arnis Lapsa

19

Không, đó chắc chắn không phải là thông lệ. Nó phản trực giác, không có cách nào chỉ nhìn vào mã để tìm ra nó làm gì. Bạn phải biết nó được sử dụng như thế nào để hiểu nó được sử dụng như thế nào.

Thay vì cung cấp các thuộc tính bằng cách sử dụng một loạt các đại biểu, các phương thức chuỗi sẽ rõ ràng hơn và hoạt động tốt hơn:

.Attribute("style", "width:100%;").Attribute("class", "test")

Mặc dù đây là một chút để gõ, nhưng nó rõ ràng và trực quan.


6
Có thật không? Tôi biết chính xác đoạn mã đó dự định khi tôi nhìn vào nó. Đó không phải là điều khó hiểu trừ khi bạn rất nghiêm khắc. Người ta có thể đưa ra lập luận tương tự về nạp chồng + cho nối chuỗi và thay vào đó chúng ta nên sử dụng phương thức Concat ().
Samantha Branham

4
@Stuart: Không, bạn không biết chính xác, bạn chỉ đoán dựa trên các giá trị được sử dụng. Bất cứ ai cũng có thể đoán, nhưng đoán không phải là một cách tốt để hiểu mã.
Guffa

11
Tôi đoán sử dụng .Attribute("style", "width:100%")mang lại cho tôi style="width:100%", nhưng với tất cả những gì tôi biết nó có thể mang lại cho tôi foooooo. Tôi không thấy sự khác biệt.
Samantha Branham

5
"Đoán dựa trên các giá trị được sử dụng" LUÔN LUÔN là những gì bạn làm khi xem mã. Nếu bạn gặp một lệnh gọi đến stream.close (), bạn cho rằng nó đóng một luồng, nhưng nó cũng có thể làm điều gì đó hoàn toàn khác.
Wouter Lievens

1
@Wouter: Nếu bạn LUÔN đoán khi đọc mã, bạn sẽ gặp khó khăn lớn khi đọc mã ... Nếu tôi thấy một cuộc gọi đến một phương thức có tên "gần gũi", tôi có thể tập hợp rằng tác giả của lớp không biết về quy ước đặt tên , vì vậy tôi sẽ rất do dự để nhận bất cứ điều gì cả về việc phương pháp này làm gì.
Guffa

17

Tôi có thể sử dụng điều này để kiếm một cụm từ không?

Magic lambda (n): một hàm lambda chỉ được sử dụng cho mục đích thay thế một chuỗi ma thuật.


vâng ... thật buồn cười và có lẽ đó là điều kỳ diệu, theo nghĩa là không an toàn thời gian biên dịch, có nơi nào việc sử dụng này sẽ gây ra thời gian chạy thay vì lỗi thời gian biên dịch không?
Maslow


16

Tất cả những lời ca ngợi về "sự kinh khủng" này là một nhóm những người c # lâu năm phản ứng thái quá (và tôi là một lập trình viên C # lâu năm và vẫn là một fan hâm mộ lớn của ngôn ngữ). Không có gì ghê gớm về cú pháp này. Nó chỉ đơn thuần là một nỗ lực để làm cho cú pháp trông giống như những gì bạn đang cố gắng diễn đạt. Càng ít "tiếng ồn" trong cú pháp cho một cái gì đó, lập trình viên có thể hiểu nó dễ dàng hơn. Giảm tiếng ồn trong một dòng mã chỉ giúp ích được một chút, nhưng hãy để sự tích lũy đó ngày càng nhiều mã hơn, và hóa ra đó là một lợi ích đáng kể.

Đây là một nỗ lực của tác giả nhằm phấn đấu cho những lợi ích tương tự mà DSL mang lại cho bạn - khi mã chỉ "trông giống như" những gì bạn đang cố nói, bạn đã đến một nơi kỳ diệu. Bạn có thể tranh luận liệu điều này có tốt cho việc can thiệp hay không, liệu nó có đủ đẹp hơn các phương thức ẩn danh để biện minh cho một số chi phí "phức tạp" hay không. Đủ công bằng ... vì vậy trong dự án của bạn, bạn nên lựa chọn đúng về việc có nên sử dụng loại cú pháp này hay không. Nhưng vẫn ... đây là một nỗ lực thông minh của một lập trình viên để làm những gì, vào cuối ngày, tất cả chúng ta đều cố gắng làm (cho dù chúng ta có nhận ra hay không). Và điều mà tất cả chúng ta đang cố gắng làm là: "Hãy nói với máy tính những gì chúng ta muốn nó làm bằng ngôn ngữ gần nhất có thể với cách chúng ta nghĩ về những gì nó muốn làm."

Đến gần hơn để thể hiện các hướng dẫn của chúng tôi với máy tính theo cách mà chúng tôi nghĩ trong nội bộ là chìa khóa để làm cho phần mềm dễ bảo trì hơn và chính xác hơn.

EDIT: Tôi đã nói "chìa khóa để làm cho phần mềm trở nên dễ bảo trì hơn và chính xác hơn", đó là một sự ngây thơ ngớ ngẩn quá mức của sự kỳ lân. Tôi đã thay đổi nó thành "một chìa khóa."


12

Đây là một trong những lợi ích của cây biểu thức - người ta có thể tự kiểm tra mã để biết thêm thông tin. Đó là cách .Where(e => e.Name == "Jamie")có thể được chuyển đổi thành mệnh đề SQL Where tương đương. Đây là một cách sử dụng thông minh của cây biểu thức, mặc dù tôi sẽ hy vọng rằng nó không đi xa hơn thế này. Bất cứ điều gì phức tạp hơn có thể sẽ khó khăn hơn mã mà nó hy vọng sẽ thay thế, vì vậy tôi nghi ngờ nó sẽ tự giới hạn.


Là một điểm hợp lệ, nhưng sự thật trong quảng cáo: LINQ đi kèm với một tập hợp các thuộc tính như TableAttribution và ColumnAttribution làm cho điều này trở thành một vấn đề hợp pháp hơn. Ngoài ra ánh xạ linq nhìn vào tên lớp và tên thuộc tính, có thể ổn định hơn so với tên tham số.
Remus Rusanu

Tôi đồng ý với bạn ở đó. Tôi đã thay đổi lập trường của mình về vấn đề này một chút sau khi đọc những gì Eric Lippert / Anders Helsberg / v.v. đã nói về vấn đề này. Tôi nghĩ rằng tôi sẽ để lại câu trả lời này vì nó vẫn còn hữu ích. Đối với những gì nó có giá trị, bây giờ tôi nghĩ phong cách làm việc với HTML này là tốt, nhưng nó không phù hợp với ngôn ngữ.
Jamie Penney

7

Đó là một cách tiếp cận thú vị. Nếu bạn giới hạn phía bên phải của biểu thức là hằng số thì bạn có thể thực hiện bằng cách sử dụng

Expression<Func<object, string>>

Mà tôi nghĩ là những gì bạn thực sự muốn thay vì đại biểu (bạn đang sử dụng lambda để lấy tên của cả hai bên) Xem triển khai ngây thơ dưới đây:

public static IDictionary<string, string> Hash(params Expression<Func<object, string>>[] hash) {
    Dictionary<string, string> values = new Dictionary<string,string>();
    foreach (var func in hash) {
        values[func.Parameters[0].Name] = ((ConstantExpression)func.Body).Value.ToString();
    }
    return values;
}

Điều này thậm chí có thể giải quyết mối quan tâm liên ngôn ngữ chéo đã được đề cập trước đó trong chuỗi.


6

Mã này rất thông minh, nhưng nó có khả năng gây ra nhiều vấn đề hơn mà nó giải quyết.

Như bạn đã chỉ ra, giờ đây có một sự phụ thuộc mơ hồ giữa tên tham số (kiểu) và thuộc tính HTML. Không có kiểm tra thời gian biên dịch được thực hiện. Nếu tên tham số bị nhập sai, trang có thể sẽ không có thông báo lỗi thời gian chạy, nhưng khó tìm lỗi logic hơn (không có lỗi, nhưng hành vi không chính xác).

Một giải pháp tốt hơn là có một thành viên dữ liệu có thể được kiểm tra tại thời điểm biên dịch. Vì vậy, thay vì điều này:

.Attributes(style => "width:100%");

mã có thuộc tính Style có thể được kiểm tra bởi trình biên dịch:

.Attributes.Style = "width:100%";

hoặc thậm chí:

.Attributes.Style.Width.Percent = 100;

Đó là công việc nhiều hơn cho các tác giả của mã, nhưng cách tiếp cận này tận dụng khả năng kiểm tra loại mạnh của C #, giúp ngăn chặn lỗi xâm nhập vào mã ngay từ đầu.


3
Tôi đánh giá cao việc kiểm tra thời gian biên dịch, nhưng tôi nghĩ vấn đề này xuất phát từ vấn đề quan điểm. Có thể một cái gì đó giống như các thuộc tính mới () {Style: "width: 100%"} sẽ thu hút được nhiều người hơn về điều này, vì nó ngắn gọn hơn. Tuy nhiên, thực hiện mọi thứ HTML cho phép là một công việc khổng lồ và tôi không thể đổ lỗi cho ai đó chỉ bằng cách sử dụng chuỗi / lambdas / lớp ẩn danh.
Samantha Branham

5

thực sự nó giống như Ruby =), ít nhất là đối với tôi, việc sử dụng tài nguyên tĩnh cho "tra cứu" động sau này không phù hợp với các cân nhắc thiết kế api, hy vọng thủ thuật thông minh này là tùy chọn trong api đó.

Chúng tôi có thể kế thừa từ IDadata (hoặc không) và cung cấp một bộ chỉ mục hoạt động như một mảng php khi bạn không cần thêm khóa để đặt giá trị. Nó sẽ là một sử dụng hợp lệ của ngữ nghĩa .net không chỉ c #, và vẫn cần tài liệu.

hi vọng điêu nay co ich


4

Theo tôi đó là lạm dụng lambdas.

Theo cú pháp sáng chói tôi thấy style=>"width:100%"khó hiểu. Đặc biệt là =>vì thay vì=


4

IMHO, đó là một cách tuyệt vời để làm điều đó. Tất cả chúng ta đều thích việc đặt tên một Trình điều khiển lớp sẽ biến nó thành một trình điều khiển trong MVC phải không? Vì vậy, có những trường hợp việc đặt tên không thành vấn đề.

Ngoài ra ý định là rất rõ ràng ở đây. Nó rất dễ hiểu .Attribute( book => "something")sẽ dẫn đến book="something".Attribute( log => "something")sẽ dẫn đếnlog="something"

Tôi đoán nó không phải là một vấn đề nếu bạn coi nó như một quy ước. Tôi cho rằng bất cứ điều gì làm cho bạn viết ít mã hơn và làm cho ý định rõ ràng là một điều tốt.


4
Đặt tên một Trình điều khiển lớp sẽ không thực hiện ngồi xổm nếu bạn cũng không kế thừa từ trình điều khiển ...
Jordan Wallwork

3

Nếu tên phương thức (func) được chọn tốt, thì đây là một cách tuyệt vời để tránh đau đầu bảo trì (ví dụ: thêm một func mới, nhưng quên thêm nó vào danh sách ánh xạ tham số chức năng). Tất nhiên, bạn cần ghi lại nhiều tài liệu và tốt hơn hết là bạn nên tự động tạo tài liệu cho các tham số từ tài liệu cho các chức năng trong lớp đó ...


1

Tôi nghĩ rằng điều này không tốt hơn "chuỗi ma thuật". Tôi không phải là một fan hâm mộ của các loại ẩn danh cho điều này. Nó cần một cách tiếp cận tốt hơn và đánh máy mạnh mẽ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.