나는MvcContrib그리드 구성 요소와 나는 매료되었지만 동시에 반발했다.그리드 구문:
.Attributes(style => "width:100%")
위 구문은 생성 된 HTML의 style 속성을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 언어에서 좋은 interop을 원할 경우 '표준'오버로드 (예 : 추가 매개 변수로 문자열 이름을 사용)를 제공해야합니다.
그 이상한 이유는이름, 왜냐하면람다는 불필요하다.; 익명 유형을 사용할 수 있고보다 유연하게 사용할 수 있습니다.
.Attributes(new { style = "width:100%", @class="foo", blip=123 });
이것은 ASP.NET MVC의 많은 부분에서 사용되는 패턴이며 (예를 들어)다른 용도(에이경고, 메모아옌데의 생각이름이 호출자 고유가 아닌 마술 값인 경우)
HtmlAttributes
클래스를 예상 속성 (IntelliSense 용)으로 채우고null
값 ... - Marc Gravell♦
그냥 내 의견을 던지고 싶었 (나는 MvcContrib 그리드 구성 요소의 저자).
이것은 분명히 언어 학대입니다. 의심의 여지가 없습니다. 그러나, 나는 그것을 직관적이라고 생각하지 않을 것입니다.Attributes(style => "width:100%", @class => "foo")
무슨 일이 벌어 졌는지는 꽤 분명하다고 생각합니다. 익명의 접근 방식보다 더 나쁜 것은 아닙니다. 인텔리 센스 관점에서, 나는 그것이 꽤 불투명하다는 것에 동의한다.
관심있는 분들을 위해 MvcContrib에서의 사용에 대한 배경 정보를 ...
개인적 취향대로 격자에 추가했습니다. 익명 형식을 사전으로 사용하는 것을 좋아하지 않습니다. "개체"를 사용하는 매개 변수는 params Func []와 같은 불투명도를 가지며 사전 컬렉션 초기화 프로그램은 다음과 같습니다. ( "style", "display : none") 속성 ( "class", "foo") 등)에 대한 여러 호출을 함께 연결해야하는 등 세부적인 유창한 인터페이스의 팬이 아닙니다.
C #에 사전 리터럴에 대한 자세한 구문이 없으면 그리드 구성 요소에 다음 구문을 포함하여 귀찮게하지 않았을 것입니다. :)
또한 MvcContrib에서이 옵션을 사용하는 것이 완전히 선택 사항임을 지적하고자합니다.이 메서드는 IDictionary를 대신 사용하는 오버로드를 감싸는 확장 메서드입니다. 이와 같은 방법을 제공하면 다른 언어와의 interop와 같이보다 일반적인 '접근법'을 지원해야한다는 것이 중요하다고 생각합니다.
또한 누군가가 '반사 오버 헤드'에 대해 언급했으며이 접근법으로 인해 오버 헤드가별로 없다는 점을 지적하고자했습니다. 런타임 반영이나 표현 컴파일이 필요하지 않습니다.http://blog.bittercoder.com/PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx).
내가 선호하는
Attributes.Add(string name, string value);
훨씬 더 명시 적이며 표준이며 lambdas를 사용하여 얻은 결과는 없습니다.
html.Attributes.Add("style", "width:100%");
다음과 같이 멋지게 읽지는 않습니다.style = "width:100%"
(생성 된 실제 html), 반면style => "width:100%"
결과 HTML에서와 매우 비슷합니다. - Jamie Penney
레일 랜드에 오신 것을 환영합니다 :)
당신이 무슨 일이 일어나고 있는지를 아는 한 실제로 아무 문제가 없습니다. (이런 종류의 문제가 잘 문서화되어 있지 않은 경우).
Rails 프레임 워크 전체는 컨벤션 오버 규칙에 기반을두고 있습니다. 이름을 붙이면 어떤 방식 으로든 그들이 사용하고있는 컨벤션에 들어갈 수 있으며 무료로 많은 기능을 사용할 수 있습니다. 명명 규칙에 따라 더 빨리 갈 수 있습니다. 모든 것이 훌륭하게 작동합니다.
이와 같은 트릭을 본 다른 곳은 Moq의 메소드 호출 어설 션입니다. 당신은 람다를 전달하지만 람다는 결코 실행되지 않습니다. 메서드 호출이 발생했는지 확인하기 위해 표현식을 사용하고 그렇지 않은 경우 예외를 throw합니다.
이것은끔찍한한 단계 이상. 그리고 아니, 이건 루비만한 건 없어요. 그것은 C #과 .Net의 남용입니다.
튜플, 익명의 타입, 유창한 인터페이스 등,보다 직선적 인 방법으로 이것을하는 방법에 대한 많은 제안이있었습니다.
그것을 그렇게 나쁜 것으로 만드는 것은 그것의 자신의 이익을 공상하는 그것의 정당한 길이다 :
VB에서 호출해야 할 때 어떻게됩니까?
.Attributes(Function(style) "width:100%")
그것의 완전 직관적 인 intellisense는 물건을 전달하는 방법을 알아내는 데 도움이되지 않습니다.
불필요하게 비효율적이다.
아무도 그것을 유지하는 방법을 전혀 모른다.
속성에 들어가는 인수의 유형은 무엇입니까?Func<object,string>
? 그 의도는 어떻게 드러나는가? 귀하의 인텔리 센스 문서는 "개체의 모든 가치를 무시하십시오"라고 말할 것입니까?
나는 당신이 그 기분을 상하게하는 것이 정당하다고 생각합니다.
나는 "문법의 광휘"캠프에 있는데, 명확하게 문서화한다면,이 괴물처럼 보입니다. 거의 문제 없습니다.
나는 이런 종류의 사용법을 거의 접하지 못했다. 나는 그것이 "부적절한 것"이라고 생각한다. :)
이것은 일반적인 사용 방법이 아니며, 일반 협약과 일치하지 않습니다. 이런 종류의 구문에는 장단점이 있습니다.
단점
찬성
결론- 공용 API 디자인에서 나는 더 명확한 방법을 선택했을 것이다.
아니, 확실히 일반적인 관행은 아닙니다. 반 직관적입니다. 코드가 무엇인지 알아낼 수있는 방법이 없습니다. 어떻게 사용했는지 이해하는 데 익숙해야합니다.
대리자 배열을 사용하여 특성을 제공하는 대신 체인 방법이 더 명확 해지고 성능이 향상됩니다.
.Attribute("style", "width:100%;").Attribute("class", "test")
입력하는 방법이 조금 더 있지만 분명하고 직관적입니다.
.Attribute("style", "width:100%")
나에게 준다.style="width:100%"
,하지만 내가 아는 모든 것을 위해 그것은 나에게 줄 수있다.foooooo
. 차이가 보이지 않습니다. - Samantha Branham
"horridness"에 대한이 모든 호언 장담은 오랜 시간 동안 C #의 사람들이 과민 반응을 겪고 있다는 것을 의미합니다 (그리고 저는 오랫동안 C #프로그래머 였고 여전히 언어에 대한 열렬한 팬이었습니다). 이 구문에 대해서는 끔찍한 것이 없습니다. 구문을 좀 더 표현하려고하는 것일뿐입니다. 구문에 구문에 "잡음"이 적 으면 적을수록 프로그래머는 더 쉽게 이해할 수 있습니다. 한 줄의 코드에서 노이즈를 줄이면 조금은 도움이되지만 점점 더 많은 코드에 걸쳐 올라 가게되면 상당한 도움이됩니다.
이것은 DSL이주는 것과 동일한 이익을 위해 노력하려는 저자의 시도입니다. 코드가 당신이 말하고자하는 것처럼 보이면, 당신은 마법의 장소에 도달했습니다. interop에 대해 이것이 좋은지 또는 "복잡성"비용의 일부를 정당화하기위한 익명 메소드보다 더 좋은지 여부에 대해 토론 할 수 있습니다. 공정하게 ... 너무 프로젝트에서 이런 종류의 문법을 사용할지 여부를 결정해야합니다. 그러나 여전히 ... 프로그래머가 영리한 시도를하는 것입니다. 하루가 끝날 무렵, 우리 모두는 (실현 여부에 관계없이) 시도하고 있습니다. 우리가하려고하는 모든 일은 다음과 같습니다. "컴퓨터로 하여금 우리가 원하는 것을 생각하는 방법에 가능한 한 가깝게 언어로하고 싶다고 말하십시오."
우리가 내부적으로 생각하는 것과 동일한 방식으로 컴퓨터에 대한 지침을 표현하는 것에 더 가까워지는 것은 소프트웨어를보다 정비 가능하고 더 정확하게 만드는 열쇠입니다.
편집 : 나는 unicorniness의 미친 듯이 순진 과장된 비트입니다 "더 maintainable하고 정확한 소프트웨어를 만드는 열쇠"라고했다. 나는 그것을 "열쇠"로 바꿨다.
문구 동전에 이걸 사용할 수 있습니까?
magic lambda (n) : 마술 끈을 대체 할 목적으로 만 사용되는 람다 함수.
이것은 표현 트리의 이점 중 하나입니다. 추가 정보를 얻기 위해 코드 자체를 검사 할 수 있습니다. 그것이 어떻게.Where(e => e.Name == "Jamie")
동일한 SQL Where 절로 변환 할 수 있습니다. 이것은 표현의 나무를 영리하게 사용하는 것입니다.하지만 이것보다 더 나아지지 않기를 희망합니다. 더 복잡한 것은 대체하려는 코드보다 어려울 수 있으므로 자체 제한이 될 것으로 판단됩니다.
흥미로운 접근 방법입니다. 표현식의 오른쪽 편을 상수로 제한하면 다음을 사용하여 구현할 수 있습니다.
Expression<Func<object, string>>
내가 생각하기에 위임자 대신 정말로 원하는 것이 있다고 생각합니다 (람다를 사용하여 양측의 이름을 얻습니다) 아래의 순진한 구현을 참조하십시오.
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;
}
이것은 스레드에서 앞에서 언급 한 상호 언어 상호 운용성 문제를 해결할 수도 있습니다.
코드는 매우 똑똑하지만 잠재적으로 더 많은 문제를 일으 킵니다.
앞에서 언급했듯이 매개 변수 이름 (스타일)과 HTML 속성 사이에는 불명확 한 종속성이 있습니다. 컴파일 시간 검사가 수행되지 않습니다. 매개 변수 이름을 잘못 입력하면 페이지에 런타임 오류 메시지가 표시되지 않지만 논리 오류 (오류는 발생하지 않지만 잘못된 동작)는 찾기가 훨씬 어려워집니다.
더 나은 솔루션은 컴파일 할 때 확인할 수있는 데이터 멤버를 갖는 것입니다. 그래서 이것 대신 :
.Attributes(style => "width:100%");
Style 속성이있는 코드는 컴파일러에서 확인할 수 있습니다.
.Attributes.Style = "width:100%";
또는:
.Attributes.Style.Width.Percent = 100;
코드 저작자가 더 많은 노력을 기울 였지만,이 접근법은 C #의 강력한 유형 검사 기능을 활용하여 버그가 처음부터 코드에 들어 가지 않도록합니다.
실제로 그것은 루비 =처럼 보입니다.) 나에게있어서 동적 인 "lookup"을위한 정적 리소스의 사용은 api 디자인 고려 사항에 맞지 않습니다.이 영리한 트릭은 api에서 선택 사항이되기를 바랍니다.
IDictionary (또는 not)로부터 상속 받아 값을 설정하기 위해 키를 추가 할 필요가 없을 때 PHP 배열처럼 동작하는 인덱서를 제공 할 수 있습니다. c #뿐만 아니라 .net 의미의 유효한 사용이 될 것이며, 여전히 문서화가 필요합니다.
이게 도움이되기를 바랍니다.
IMHO, 그것을하는 멋진 방법입니다. 클래스 컨트롤러의 이름을 지정하면 MVC 권한의 컨트롤러가됩니다. 그래서 명명이 중요 할 때가 있습니다.
또한 여기서 의도가 매우 분명합니다. 그것은 매우 이해하기 쉽습니다..Attribute( book => "something")
결과는book="something"
과.Attribute( log => "something")
결과는log="something"
컨벤션처럼 취급한다면 문제가 될 수 없습니다. 나는 당신이 코드를 적게 만들고 의도를 명확하게 만드는 것이 무엇이든 좋은 것이라고 생각합니다.
내 견해로는 람다를 학대하는 것이다.
구문 광휘에 관해서는style=>"width:100%"
명백한 혼란. 특히 때문에=>
대신에=
메서드 (func) 이름을 잘 선택하면 유지 보수 문제를 피할 수있는 훌륭한 방법입니다 (예 : 새 func를 추가했지만 함수 - 매개 변수 매핑 목록에 추가하지 않은 경우). 물론, 문서를 많이 문서화해야하고 해당 클래스의 함수에 대한 문서의 매개 변수에 대한 문서를 자동 생성하는 것이 좋습니다 ...
나는 이것이 "마법의 끈"보다 낫지 않다고 생각한다. 나는 이것을 위해 익명의 유형을 많이 좋아하지 않는다. 더 나은 & 강하게 타자를 치는 접근.