C#变得更难阅读了吗?


15

随着C#的进步,添加了许多语言功能。对我来说,它已经变得难以理解了。

作为一个例子,考虑Caliburn.Micro代码下面的代码剪断这里

            container = CompositionHost.Initialize(
                   new AggregateCatalog(
                      AssemblySource.Instance.
                             Select(x => new AssemblyCatalog(x))
                               .OfType<ComposablePartCatalog>()
                )
            );

现在,这只是一个小例子。

我有几个问题:

  • 这是常见问题还是已知问题?
  • C#社区是否找到相同的东西?
  • 这是语言问题还是开发人员使用的样式?

是否有任何简单的解决方案可以更好地理解其他代码并避免以这种方式编写代码?


6
它是lambda函数,在您真正掌握它们之前很难阅读它们。
Ryathal 2012年

9
我认为您确实不像您想象的那样了解语法。通过练习,您的示例很简单。
ChaosPandion 2012年

6
@托马斯·欧文斯:天哪,至少给我们一些时间来编辑问题,使问题保持​​开放。15分钟?快过来
史蒂文·埃弗斯

4
@DannyVarod:1.回答“否”是不可接受的。2.已关闭问题。3.如果您同意不应该在此处提问,请标记/投票以将其关闭或编辑为更好
史蒂文·埃弗斯

2
@ThorbjørnRavn Andersen-一个巴掌能学到什么?没有任何信息!

Answers:


12

快速注释一下该语言在哪里应该清除它:C#是一种通用编程语言;不像C(像C ++)那样,它追求高度抽象;与Lisp方言不同,它的目标是实用的表达方式,与Java不同,它的驱动力更强-微软可以迅速响应需求。

这就是为什么它将LINQ,lambda和奇怪的新关键字混合在一起的原因-它迅速适应了新的问题领域,而确实是一种向如此复杂的语言倾斜的道路,以至于很少有人可以正确使用它(例如C ++)。这不是C#本身的问题,而是具有这些宏伟目标的任何语言的问题。

社区已经意识到了这一点,更重要的是,C#背后的家伙也敏锐地意识到了这一点(关于C#5.0中新增功能背后的一些博客条目和播客显示了这些家伙想要使事情保持简单的程度)。微软正在努力减轻其旗舰产品的负担,以免成为旗舰产品:推出DLR,这是新语言(F#)的亮点。

此外,根据问题,有关C#的课程材料(包括MS认证)建议使用不同(但一致)的C#使用风格-选择武器并坚持使用:某些问题上使用流利的LINQ,其他问题上使用TPL的lambda,简单-大多数。


2
您能用“不同于Lisp的方言来实现实际表现力”来解释您的意思吗?
Giorgio

27

不,C#为我们提供了更多简洁地编写代码的选项。这可以被使用或滥用。如果使用得当,它将使代码更易于阅读。如果使用不当,可能会使代码难以阅读。但是,糟糕的程序员始终具有编写难以阅读的代码的技能。

让我们举两个例子,两个都是基于在StackOverflow上找到的关于同一问题的例子,并找到具有特定属性的类型:

C#2.0:

static IEnumerable<Type> GetTypesWithAttribute<TAttribute>(bool inherit) 
                              where TAttribute: System.Attribute
{
    foreach(Assembly assembly in AppDomain.Current.GetAssemblies())
    {
        foreach(Type type in assembly.GetTypes()) 
        {
            if (type.IsDefined(typeof(TAttribute),inherit))
                yield return type;
        }
    }
}

C#4.0:

IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit) 
                              where TAttribute: System.Attribute
{ 
    return from assembly in AppDomain.CurrentDomain.GetAssemblies()
           from type in assembly.GetTypes()
           where type.IsDefined(typeof(TAttribute),inherit)
           select type;
}

恕我直言,新语法使其更易于阅读。


新语法确实更容易阅读,但更容易理解,例如引擎盖下发生了什么?第一个示例是可以理解的,第二个示例则更具可读性。
nawfal 2012年

4
@nawfal以我的经验,与linq语句相比,人们在理解“收益率回报”结构时要麻烦得多;所以我认为第二种方法更具可读性和可理解性。两者都无法真正告诉您幕后情况,因为两者都映射到与处理器实际工作方式相去甚远的抽象。
2013年

老实说,我不喜欢LINQ,因为它抽象了循环,并鼓励编码人员在单独的LINQ查询(在后台有单独的循环)中检索数据,而不是在具有更复杂核心的循环中检索数据。
mg30rg

8

当添加LINQ时,它普及了一种编码样式,其中涉及许多Fluent样式的方法链,并传递了lambda作为参数。

适应后,此样式将非常强大。但是,可能会滥用它来制作相当不可读的代码。我认为您的示例并不算太糟糕,尽管缩进是随机的(这是这种代码风格的共同特征,Visual Studio不会非常一致地自动缩进)。

在我的工作场所中,我们在今年初审查我们的编码标准时讨论了这种编码风格,我们决定鼓励开发人员分解这样的代码:特别是不要在函数调用中创建和初始化匿名对象。因此,您的代码将变为:

var assemblyCatalog = AssemblySource.Instance
    .Select(x => new AssemblyCatalog(x))
    .OfType<ComposablePartCatalog>();
var aggregateCatalog = new AggregateCatalog(assemblyCatalog);
container = CompositionHost.Initialize(aggregateCatalog);

1
创建一个新类型然后在此之后立即动态打开该类型,这有点奇怪吗?
DeadMG 2012年

大概,我只是切掉了代码片段,而没有真正考虑它的意图。只是想将所有实例都拆分成自己的代码行,以显示对代码外观的影响。
Carson63000

我为缩进:()负责。这是原始文件:devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/…– 2012

1
我完全同意这个答案。示例代码段中的问题不是新的C#语法,而是编写者尝试使用“单一代码”代码来变得聪明的问题。有一个古老的规则可以追溯到UNIX:一切都只能做一件事情,并且做得很好。它适用于类,适用于方法,当然,当然也适用于代码行。
Laurent Bourgault-Roy

4

您示例中的代码不容易阅读,因为

  • 它将许多概念(组成,目录,集合,组合件,可组合零件...)与多层嵌套混合在一起,而调用代码通常只应处理一层。看起来有点像违反Demeter法则,仅使用嵌套方法调用而不是子属性子链。这使代码行背后的意图有些混乱。

  • 单例用法很奇怪- AssemblySource.Instance.Select()意味着Instance是IEnumerable,这有点尴尬。

  • lambda表达式中的x变量很难看。通常,您尝试给lambda变量起意的显示名称-帮助读者识别该函数所涉及的数据类型,即使他不熟悉lambda。

  • 目前尚不清楚为什么要使用OfType<T>()刚创建的对象集合进行过滤...

但是,所有这些缺陷都与原始开发人员编写代码的方式以及他设计代码的表达方式有关。这不是最新版本的C#和lambda表达式的外观所特有的。

更一般而言,如果您的代码阅读者知道lambda的工作原理,那么它会有所帮助,但是通过足够清晰的命名,您几乎总是可以使您的代码可读,即使是具有.NET 3.5之前版本的背景。


2

每当流行语言的新版本获得新的构造时,就会发生类似的辩论。

几年前,我也有这些疑问(http://gsscoder.blogspot.it/2009/08/use-csharps-features-wisely.html)。

我认为C#正在以一种优雅而一致的方式发展。

样本中的代码并不复杂,也许您不使用lamda表达式。

问题在于C#不仅是一种面向对象的语言,它现在还支持功能构造(http://archive.msdn.microsoft.com/FunctionalCSharp/)。


1

我花了一些时间来了解Lambda语法,而且我是数学和物理方面的背景。这有点类似于数学表达式,尽管它们使用->而不是=>:

数学示例 f(x):= x-> x + 2读为“ x的函数f定义为x映射到x + 2上

c#示例 del myDelegate = x => x +2; 读取为“ myDelegate是一个函数,myDelegate(x)将x映射到x + 2

数学和编程之间的不一致并没有真正的帮助,尽管我认为->已经在C ++中被视为“属性”(urrgghh!)

http://en.wikipedia.org/wiki/List_of_mathematical_symbols


“尽管我想->在C ++中已经被当作“属性”(urrgghh!)使用了,好像!在C ++中,可怜的意思是“动态分配的属性...”。如果不是动态的,则可以像其他所有语言一样使用句点。
mg30rg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.