我看着MvcContrib网格组件,我很着迷,但同时又被网格语法中使用的语法技巧所排斥:

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

上面的语法将生成的HTML的样式属性设置为width:100%。如果你注意的话,'style'并没有被指定。它是从表达式中参数的名称推导出来的!我必须深入研究这个问题,找到“魔法”发生的地方:

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

因此,代码确实使用了正式的、编译时的参数名称来创建属性名称-值对的字典。生成的语法结构确实非常具有表现力,但同时也非常危险。

lambda表达式的一般用法允许替换所使用的名称而不产生副作用。我在一本书上看到一个例子,上面写着收藏。我知道我可以在我的代码集合中写。ForEach(log => fire。burn (log))它的意思是一样的。但是使用这里的MvcContrib Grid语法,我突然发现代码可以根据我为变量选择的名称主动查找并做出决定!

那么这是c# 3.5/4.0社区和lambda表达式爱好者的普遍做法吗?还是说,我不应该担心一个流氓的诡计特立独行?


当前回答

两个都是。这是对lambda表达式和语法的滥用。

其他回答

这是表达式树的好处之一——可以检查代码本身以获得额外的信息。这就是如何将.Where(e => e. name == "Jamie")转换为等效的SQL Where子句。这是表达式树的一种巧妙使用,尽管我希望它不会超出这个范围。任何更复杂的代码都可能比它希望取代的代码更难,因此我怀疑它将是自我限制的。

这不仅在一个层面上是可怕的。不,这一点也不像露比。这是对c#和。net的滥用。

关于如何以更直接的方式实现这一点,已经有许多建议:元组、匿名类型、流畅接口等等。

它之所以如此糟糕,是因为它只是为了自己的利益而幻想:

What happens when you need to call this from Visual Basic? .Attributes(Function(style) "width:100%") It's completely counter intuitive, and intellisense will provide little help figuring out how to pass stuff in. It's unnecessarily inefficient. Nobody will have any clue how to maintain it. What is the type of the argument going in to attributes? is it Func<object,string>? How is that intention revealing? What is your intellisense documentation going to say, "Please disregard all values of object"?

我认为你完全有理由感到厌恶。

在我看来,这是对羔羊的滥用。

至于语法辉煌,我发现style=>"width:100%"平原混乱。特别是因为=>而不是=

恕我直言,这是一种很酷的方式。我们都喜欢将类命名为控制器将使其成为MVC中的控制器,对吧?所以在某些情况下,命名确实很重要。

这里的意图也很明确。很容易理解,.Attribute(book= > "something")将导致book="something", .Attribute(log= > "something")将导致log="something"

我想如果你把它当作一种惯例来对待,那应该不成问题。我的观点是,只要能让你写更少的代码,让你的意图更明显,那就是一件好事。

只是想提出我的观点(我是MvcContrib网格组件的作者)。

毫无疑问,这绝对是语言滥用。然而,我不会真的认为这是反直觉的-当你看一个属性的调用(style => "width:100%", @class => "foo") 我认为这是非常明显的(它当然不比匿名类型方法更糟糕)。从智能感知的角度来看,我同意这是相当不透明的。

对于那些感兴趣的人,它在MvcContrib中使用的一些背景信息…

我把它添加到网格作为个人偏好-我不喜欢使用匿名类型作为字典(有一个接受“object”的参数就像一个接受参数Func[]一样不透明)和字典集合初始化器相当冗长(我也不喜欢冗长的流畅接口,例如必须将多个调用链接到一个属性(“style”,“display:none”)。属性("class", "foo")等)

如果c#对字典字面量有一个不那么冗长的语法,那么我就不会在网格组件中包含这个语法了:)

我还想指出,在MvcContrib中使用这个是完全可选的-这些是扩展方法,包装重载,以字典代替。我认为重要的是,如果你提供了这样的方法,你也应该支持更“正常”的方法,例如与其他语言的互操作。

另外,有人提到了“反射开销”,我只是想指出,这种方法真的没有太多的开销——没有运行时反射或表达式编译(参见http://blog.bittercoder.com/PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx)。