我正在看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));}
}

实际上,代码使用正式的编译时,参数名来创建属性名称 - 值对的字典。 结果语法结构确实非常具有表现力,但同时也非常危险。 lambda表达式的一般用法允许替换使用的名称而没有副作用。 我在一本书中看到了一个例子,上面写着collection.ForEach(book => Fire.Burn(book))我知道我可以在我的代码collection.ForEach(log => Fire.Burn(log))编写collection.ForEach(log => Fire.Burn(log)) 它意味着相同事情 。 但是在这里突然使用MvcContrib Grid语法,我发现代码主动查找并根据我为变量选择的名称做出决定!

这是C#3.5 / 4.0社区和lambda表达爱好者的常见做法吗? 或者是一个我不应该担心的流氓一招特立独行?


#1楼

我会比较喜欢

Attributes.Add(string name, string value);

它更加明确和标准,并且使用lambdas没有获得任何东西。


#2楼

这是表达式树的一个好处 - 可以检查代码本身以获取额外信息。 这就是.Where(e => e.Name == "Jamie")可以转换为等效的SQL Where子句。 这是表达树的巧妙使用,但我希望它不会比这更进一步。 任何更复杂的东西都可能比它希望取代的代码更难,所以我怀疑它会自我限制。


#3楼

我正处于“语法上的光彩”阵营,如果他们清楚地记录下来,看起来很酷,它几乎没有问题!


#4楼

欢迎来到Rails Land :)

只要你知道发生了什么,它就没有什么不妥。 (当这种事情没有很好地证明存在问题时)。

整个Rails框架建立在约定优于配置的基础上。 以某种方式命名事物可以将您锁定到他们正在使用的约定中,并且您可以免费获得大量功能。 遵循命名约定可以让您更快地到达目的地。 整个过程非常出色。

另一个我见过这样的技巧的地方是Moq中的方法调用断言。 你传入一个lambda,但lambda永远不会被执行。 他们只是使用表达式来确保方法调用发生,如果没有则抛出异常。


#5楼

这有很差的互操作性。 例如,考虑这个C# - F#示例

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")

结果:

印有“arg”(不是“yadda”)。

因此,库设计者应该避免这种“滥用”,或者至少提供“标准”重载(例如,将字符串名称作为额外参数),如果他们想要在.Net语言之间进行良好的互操作。


#6楼

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

这不是一种常用的使用方式,它与一般惯例不一致。 这种语法当然有利有弊:

缺点

优点

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


#7楼

不,这当然不常见。 这是违反直觉的,没有办法只看代码来弄清楚它的作用。 你必须知道如何使用它来理解它是如何使用的。

链接方法不是使用委托数组提供属性,而是更清晰,性能更好:

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

虽然输入的内容多一点,但它清晰直观。


#8楼

如果方法(func)名称被很好地选择,那么这是避免维护麻烦的一种很好的方法(即:添加新的func,但忘记将其添加到函数参数映射列表中)。 当然,您需要对其进行大量记录,并且最好从该类中的函数的文档中自动生成参数的文档...


#9楼

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

至于语法上的亮度,我发现style=>"width:100%"简直令人困惑。 特别是因为=>而不是=


#10楼

代码非常聪明,但它可能会导致更多问题解决。

正如您所指出的,现在参数名称(样式)和HTML属性之间存在模糊的依赖关系。 没有编译时间检查。 如果参数名称输入错误,页面可能不会有运行时错误消息,但更难找到逻辑错误(没有错误,但行为不正确)。

更好的解决方案是拥有一个可以在编译时检查的数据成员。 所以不是这样的:

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

编译器可以检查具有Style属性的代码:

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

甚至:

.Attributes.Style.Width.Percent = 100;

这对代码的作者来说更有用,但这种方法利用了C#强大的类型检查功能,这有助于防止错误首先进入代码。


#11楼

我觉得奇怪的不是因为这个名字 ,而是因为lambda是不必要的 ; 它可以使用匿名类型并且更灵活:

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

这是在ASP.NET MVC的大部分中使用的模式(例如),并且有其他用途 ( 需要注意的是 ,如果名称是魔术值而不是调用者特定,请注意Ayende的想法 )


#12楼

实际上它看起来像Ruby =),至少对我来说,为后来的动态“查找”使用静态资源不适合api设计考虑因素,希望这个聪明的技巧在api中是可选的。

我们可以从IDictionary继承(或不继承)并提供一个索引器,当你不需要添加一个键来设置一个值时,它就像一个php数组。 它将是.net语义的有效使用,而不仅仅是c#,仍然需要文档。

希望这可以帮助


#13楼

这在多个层面上都很糟糕 。 不,这与Ruby不同。 这是对C#和.Net的滥用。

关于如何以更直接的方式做到这一点有很多建议:元组,匿名类型,流畅的界面等等。

让它变得如此糟糕的原因在于它只是想要自己的好处:

  • 当你需要从VB调用它时会发生什么?

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

  • 它完全反直觉,智能感知将无法帮助确定如何传递内容。

  • 它的效率不必要地低效。

  • 没有人会知道如何维护它。

  • 进入属性的参数类型是什么,它是Func<object,string> ? 这个意图是如何揭示的。 您的intellisense文档会说什么,“请忽略对象的所有值”

我觉得你有充分的理由感到有这种反感。


#14楼

他们都。 它是lambda表达式语法亮度的滥用。


#15楼

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

这绝对是语言滥用 - 毫无疑问。 但是,当你看一下对Attributes(style => "width:100%", @class => "foo")的调用Attributes(style => "width:100%", @class => "foo")时,我真的不会认为这是反直觉的。
我认为这很明显是什么(它肯定不比匿名类型方法更糟)。 从智能理论的角度来看,我同意这是非常不透明的。

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

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

如果C#对字典文字的语法不那么冗长,那么我就不会在网格组件中包含这种语法了。

我还想指出在MvcContrib中使用它是完全可选的 - 这些是包含带有IDictionary的重载的扩展方法。 我认为重要的是,如果您提供这样的方法,您还应该支持更“正常”的方法,例如与其他语言互操作。

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


#16楼

恕我直言,这是一种很酷的方式。 我们都喜欢这样一个事实,即命名一个类Controller会使它成为MVC中的控制器吗? 因此,有些情况下命名很重要。

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

我想如果你把它当成一种惯例,那应该不是问题。 我认为无论是什么让你编写更少的代码并使意图明显是一件好事。


#17楼

这是一个有趣的方法。 如果您将表达式的右侧约束为常量,那么您可以实现使用

Expression<Func<object, string>>

我认为这是你真正想要的而不是委托(你使用lambda来获取双方的名字)参见下面的天真实现:

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;
}

这甚至可以解决线程中前面提到的跨语言互操作问题。


#18楼

我可以用它来拼写短语吗?

magic lambda(n):一个lambda函数,仅用于替换魔术字符串。


#19楼

我认为这并不比“魔术弦”好。 对于这个,我不太喜欢匿名类型。 它需要一种更好的强类型方法。


#20楼

以下是什么问题:

html.Attributes["style"] = "width:100%";

#21楼

所有这些关于“可怕”的咆哮都是一群反复过度的长期c#家伙(而且我是一名长期的C#程序员,并且仍然是该语言的忠实粉丝)。 这种语法没什么可怕的。 它只是试图使语法看起来更像你想要表达的内容。 语法中的“噪音”越少,程序员就越容易理解它。 减少一行代码中的噪声只会有所帮助,但是让它在越来越多的代码中积累,结果证明是一个重大的好处。

这是作者试图争取DSL给你的同样的好处 - 当代码只是“看起来像”你想说的时候,你已经到了一个神奇的地方。 您可以讨论这是否适用于互操作,或者它是否比匿名方法更好,以证明某些“复杂性”成本。 足够公平......所以在你的项目中你应该正确选择是否使用这种语法。 但仍然......这是一个程序员做一些聪明的尝试,在一天结束时,我们都在尝试做(无论我们是否意识到)。 而我们所有人都想做的是:“告诉计算机我们希望用尽可能接近我们想要做什么的语言做什么。”

以与我们内部思考相同的方式接近向计算机表达我们的指令是使软件更易于维护和更准确的关键。

编辑:我曾说过“使软件更易于维护和更准确的关键”,这是一种疯狂的过分夸大的独特性。 我把它变成了“一把钥匙”。

反映参数名称:滥用C#lambda表达式还是语法亮度?相关推荐

  1. Lambda表达式的语法格式

    Lambda表达式的语法格式: 参数列表 => 语句或语句块 "Lambda表达式"是委托的实现方法,所以必须遵循以下规则: 1)"Lambda表达式"的 ...

  2. 变量不合法的表达式JAVA_Java8中lambda表达式的语法,别人都会的,你还不会吗?「一」...

    函数式编程 函数式编程是一种编程方式,它将电脑运算视为函数的计算.函数编程语言最重要的基础是λ演算(lambda calculus),λ演算的函数可以接受函数当作输入(参数)和输出(返回值). 函数式 ...

  3. Java 8 Lambda表达式基础语法

    /*** * 一.Lambda 表达式的基础语法:* Java8中引入了要给新的操作符 "->" 该操作符称作箭头操作符 或 Lambda操作符* 箭头操作符将Lambda拆 ...

  4. Python中lambda表达式的语法与应用

    lambda表达式常用来声明匿名函数,也就是没有名字的.临时使用的小函数,虽然也可以使用lambda表达式定义具名函数,但很少这样使用. lambda表达式常用在临时需要一个于函数的功能但又不想定义函 ...

  5. lambdapython语法_Python中lambda表达式的语法与应用

    lambda表达式常用来声明匿名函数,也就是没有名字的.临时使用的小函数,虽然也可以使用lambda表达式定义具名函数,但很少这样使用. lambda表达式常用在临时需要一个于函数的功能但又不想定义函 ...

  6. lambda表达式的语法精简

    package lambda.syntax;import lambda.interfaces.LambdaSingleMutipleParamter; import lambda.interfaces ...

  7. Lambda表达式的语法与如何使用Lambda表达式

    Lambda表达式是对象,是一个函数式接口的实例 如何来写Lambda表达式? 看参数 看返回值 代码实例1: package day2;import jdk.nashorn.internal.cod ...

  8. 【Kotlin】函数 ⑥ ( 函数参数为 Lambda 表达式 | Lambda 表达式作为参数的简略写法 | 唯一参数的简略写法 | 最后一个参数的简略写法 )

    文章目录 一. 函数参数为 Lambda 表达式 二.Lambda 表达式作为参数的简略写法 1.Lambda 表达式作为唯一参数的简略写法 2.Lambda 表达式作为最后一个参数的简略写法 一. ...

  9. Kotlin系列之Lambda表达式(1)

    今天开始后续的几篇Kotlin的文章会介绍Kotlin中Lambda表达式相关的内容. 什么是Lambda表达式 在Java8中引入了Lambda表达式,这是最令Java开发者激动和期待的一个功能.那 ...

最新文章

  1. openblas 矩阵算法库 简介
  2. VMware安装MikroTik RouterOS chr
  3. VMware VCP
  4. Java大数加法乘法减法、36进制加法
  5. Spring Cloud Sleuth 中id的使用
  6. vue图片压缩不失真_图片压缩会失真?快试试这几个无损压缩神器。
  7. java英文拼写检查并自动纠正
  8. 关于生命周期函数dealloc的使用小结
  9. XCode5 文档下载地址
  10. Couldn't find leader offsets for Set news_topic
  11. 小米10开始抓取日志怎么关闭_日志MIUI 10 9.5.22 内测更新资讯
  12. 计算机音频视频格式名,MP3/MP4播放器固件知识常见问题解决
  13. pip升级scapy报错It is a distutils installed project and thus we cannot accurately determine which files
  14. 洛谷 [P3110] 驮运
  15. 计算机的输入和输出设备
  16. 两台虚拟服务器如何串联,两台tp-link路由器串联设置教程 | 192路由网
  17. pdf怎么提取页面,pdf页面提取方法
  18. RedHat上面部署iObjects C++
  19. opencvsharp图像处理_腐蚀与膨胀,击中击不中变换(3)
  20. 开发小组共同使用协同文档

热门文章

  1. Visual Assist使用详细说明
  2. 多线程总结-JUC中常用的工具类
  3. 相机原理updateTexImage
  4. 【剑指offer-Java版】18树的子结构
  5. 一文读懂MQTT协议
  6. 一个不错的android学习网站
  7. 互联网思维-NO.1思维(2)
  8. 安装搭建kafka集群
  9. LeetCode 6 Z字形变换
  10. 文件管理系统_我的文件管理系统