我看着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表达式爱好者的普遍做法吗?还是说,我不应该担心一个流氓的诡计特立独行?


当前回答

这不仅在一个层面上是可怕的。不,这一点也不像露比。这是对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"?

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

其他回答

我认为这不比“魔术弦”好多少。在这方面,我也不太喜欢匿名类型。它需要一种更好的强类型方法。

我发现奇数不是因为它的名字,而是因为没有必要;它可以使用匿名类型,并且更加灵活:

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

这是在很多ASP中使用的模式。NET MVC(例如),并有其他用途(注意,如果名称是一个魔法值,而不是特定于调用者,也要注意Ayende的想法)

我几乎没有遇到过这种用法。我认为这是“不合适的”:)

这不是一种常用的使用方式,它不符合一般的约定。当然,这种语法也有优点和缺点:

Cons

代码不是直观的(通常的约定是不同的) 它往往是脆弱的(重命名参数将破坏功能)。 测试起来有点困难(伪造API需要在测试中使用反射)。 如果大量使用表达式,它会变慢,因为需要分析参数而不仅仅是值(反射成本)。

Pros

在开发人员调整到这种语法之后,它的可读性更强。

底线——在公共API设计中,我会选择更明确的方式。

我更喜欢

Attributes.Add(string name, string value);

它更加明确和标准,使用lambdas什么也得不到。

如果方法(func)名称选择得当,那么这是避免维护头痛的好方法(例如:添加一个新的func,但忘记将其添加到函数参数映射列表中)。当然,你需要对它进行大量的文档记录,你最好从该类函数的文档中自动生成参数的文档……