[C#] 매개 변수 이름을 반영 : C # 람다 식의 남용 또는 구문 광택?
MvcContrib Grid 구성 요소를 보고 있으며 Grid 구문에 사용되는 구문 트릭에 매료되었지만 동시에 격퇴되었습니다 .
.Attributes(style => "width:100%")
위의 구문은 생성 된 HTML의 스타일 속성을로 설정합니다 width:100%
. 이제주의를 기울이면 ‘스타일’은 어디에도 지정되지 않으며 표현식의 매개 변수 이름 에서 추론됩니다 ! 나는 이것을 파헤쳐 서 ‘매직’이 일어나는 곳을 찾았습니다.
Hash(params Func<object, TValue>[] hash)
{
foreach (var func in hash)
{
Add(func.Method.GetParameters()[0].Name, func(null));
}
}
실제로 코드는 형식, 컴파일 시간, 매개 변수 이름을 사용하여 속성 이름-값 쌍의 사전을 만듭니다. 결과 구문 구조는 실제로 매우 표현력이 뛰어나지 만 동시에 매우 위험합니다. 람다 식을 일반적으로 사용하면 부작용없이 사용 된 이름 을 대체 할 수 있습니다 . 나는라는 책에서 예를 볼 collection.ForEach(book => Fire.Burn(book))
나는 내 코드에서 쓸 수 있습니다 알고 collection.ForEach(log => Fire.Burn(log))
그리고 그것은 같은 일을 의미합니다 . 그러나 MvcContrib Grid 구문이 갑자기 여기에서 변수에 대해 선택한 이름을 기반으로 적극적으로보고 결정하는 코드를 찾습니다!
C # 3.5 / 4.0 커뮤니티 및 람다 식 애호가들과의 공통 관행입니까? 아니면 내가 걱정해서는 안되는 불량한 트릭 매버릭입니까?
답변
상호 운용성이 좋지 않습니다. 예를 들어,이 C #-F # 예를 고려하십시오.
씨#:
public class Class1
{
public static void Foo(Func<object, string> f)
{
Console.WriteLine(f.Method.GetParameters()[0].Name);
}
}
에프#:
Class1.Foo(fun yadda -> "hello")
결과:
“arg”가 인쇄됩니다 ( “yadda”아님).
결과적으로 라이브러리 설계자는 이러한 종류의 ‘부적절 함’을 피하거나 .Net 언어에서 좋은 상호 운용성을 원할 경우 최소한 ‘표준’과부하 (예 : 문자열 이름을 추가 매개 변수로 사용)를 제공해야합니다.
답변
나는 이름 때문에 그다지 이상한 것이 아니라 람다가 불필요 하기 때문에 ; 익명 유형을 사용하고 더 유연 할 수 있습니다.
.Attributes(new { style = "width:100%", @class="foo", blip=123 });
이 ASP.NET MVC (예를 들어)의 대부분에 사용되는 패턴이며,이 다른 용도 (A 주의 , 참고도 Ayende의 생각을 이름이 마법의 값이 호출 별이 아닌 경우)
답변
내 의견을 던지고 싶었습니다 (MvcContrib 그리드 구성 요소의 저자입니다).
이것은 분명히 언어 남용입니다. 의심 할 여지가 없습니다. 그러나, 나는 그것이 직감적으로 직관적이라고 생각하지 않을 것입니다-당신이 전화를 볼 때 Attributes(style => "width:100%", @class => "foo")
나는 무슨 일이 일어나고 있는지 분명하다고 생각합니다 (익명 유형 접근법보다 나쁘지 않습니다). 지능적인 관점에서 나는 그것이 불투명하다는 데 동의합니다.
관심있는 사람들을 위해 MvcContrib에서의 사용에 대한 배경 정보는 …
나는 이것을 개인 취향으로 그리드에 추가했다. 나는 익명의 타입을 사전으로 사용하는 것을 좋아하지 않는다 ( “object”를 취하는 매개 변수가 Func []라는 매개 변수를 갖는 것만 큼 불투명하다). 오히려 장황한 (또한 Attribute ( “style”, “display : none”). Attribute ( “class”, “foo”) 등에 대한 여러 호출을 함께 연결해야하는 장황한 인터페이스의 팬이 아닙니다.
C #에 사전 리터럴에 대한 덜 장황한 구문이 있으면 그리드 구성 요소 에이 구문을 포함시키지 않아도됩니다. 🙂
또한 MvcContrib에서 이것을 사용하는 것은 선택 사항입니다. 이들은 대신 IDictionary를 사용하는 과부하를 감싸는 확장 방법입니다. 이와 같은 방법을 제공하는 경우 다른 언어와의 상호 운용을 위해보다 ‘일반적인’접근 방식도 지원해야합니다.
또한 누군가가 ‘반사 오버 헤드’를 언급 했으며이 접근법에는 실제로 오버 헤드가 많지 않다는 것을 지적하고 싶었습니다. 런타임 리플렉션이나 표현식 컴파일이 없습니다 ( http://blog.bittercoder.com 참조) /PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx ).
답변
내가 선호하는
Attributes.Add(string name, string value);
훨씬 더 명확하고 표준이며 람다를 사용하여 얻은 것은 없습니다.
답변
Rails Land에 오신 것을 환영합니다 🙂
무슨 일이 일어나고 있는지 아는 한 아무런 문제가 없습니다. (이런 종류의 문제가 문서화되지 않은 경우입니다).
Rails 프레임 워크 전체는 컨피규레이션에 대한 컨벤션에 기반을두고 있습니다. 특정 방식으로 이름을 지정하면 사용중인 컨벤션에 참여하게되며 많은 기능이 무료로 제공됩니다. 명명 규칙을 따르면 더 빨리가는 곳으로 갈 수 있습니다. 모든 것이 훌륭하게 작동합니다.
이와 같은 트릭을 본 또 다른 곳은 Moq의 메소드 호출 어설 션입니다. 람다를 전달하지만 람다는 절대 실행되지 않습니다. 단지 표현식을 사용하여 메소드 호출이 발생했는지 확인하고 그렇지 않은 경우 예외를 발생시킵니다.
답변
이것은 하나 이상의 수준에서 끔찍 합니다. 그리고 아니, 이것은 루비와 같은 것이 아닙니다. C #과 .Net의 남용입니다.
튜플, 익명 형식, 유창한 인터페이스 등과 같이보다 직접적인 방법으로이를 수행하는 방법에 대한 제안이 많이있었습니다.
그렇게 나쁘게 만드는 것은 자신의 이익을 위해 공상하는 올바른 방법이라는 것입니다.
-
VB에서 이것을 호출하면 어떻게됩니까?
.Attributes(Function(style) "width:100%")
-
직관적으로 지능적인 인텔리전스를 사용하면 물건을 전달하는 방법을 알아내는 데 거의 도움이되지 않습니다.
-
불필요하게 비효율적입니다.
-
아무도 그것을 유지하는 방법에 대한 단서가 없습니다.
-
속성에 들어가는 인수의 유형은 무엇입니까
Func<object,string>
? 그 의도가 어떻게 드러납니까? “문서의 모든 값을 무시하십시오”라는 지적 문서는 무엇입니까?
나는 당신이 그런 반감을 느끼는 것을 완전히 정당화했다고 생각합니다.
답변
나는 “신택스 브릴 리언 스 (Syntax Brilliance)”캠프에있다. 만약 그들이 그것을 명확하게 문서화하고, 그것이이 굉장히 멋지다고 생각한다면, 그것은 거의 문제가 없다!