最佳的LINQ查询格式化方法

53

在你忽略或投票关闭这个问题之前,我认为这是一个值得提出的问题,因为代码清晰度是一个重要的讨论话题,它对编写可维护的代码至关重要,我非常希望那些曾经遇到过这个问题的人能够给出答案。

最近我遇到了这个问题,由于嵌套层数较多,LINQ查询很容易变得非常复杂。

以下是我为同一相对不复杂的查询所想出的格式差异的一些示例:

无格式

var allInventory = system.InventorySources.Select(src => new { Inventory = src.Value.GetInventory(product.OriginalProductId, true), Region = src.Value.Region }).GroupBy(i => i.Region, i => i.Inventory);

提高格式化

var allInventory = system.InventorySources
    .Select(src => 
        new { 
            Inventory = src.Value.GetInventory(product.OriginalProductId, true), 
            Region = src.Value.Region })
                .GroupBy(
                    i => i.Region, 
                    i => i.Inventory);

块级格式化

var allInventory = system.InventorySources
    .Select(
        src => new 
        { 
            Inventory = src.Value.GetInventory(product.OriginalProductId, true), 
            Region = src.Value.Region 
        })
        .GroupBy(
            i => i.Region, 
            i => i.Inventory
        );

列表格式化

var allInventory = system.InventorySources
    .Select(src => new { Inventory = src.Value.GetInventory(product.OriginalProductId, true), Region = src.Value.Region })
    .GroupBy(i => i.Region, i => i.Inventory);

我希望制定一种标准的linq格式,以最大化可读性和理解,并使其看起来整洁和专业。到目前为止,我无法决定,所以我把这个问题转给了这里的专业人士。


看一下 ReSharper 和 CodeRush。它们都为 LINQ 语句和查询理解提供自动格式化。我发现它们在生成易读、易懂的格式方面做得很好。 - LBushkin
5
我使用Resharper,它在Linq格式设置方面常常不一致,并且会在各个地方添加奇怪的缩进。 - Aren
1
为什么不使用linq语法糖:(from src in system.InventorySources groupby iRegion, i.Inventory select new { Inventory = src.Value.GetInventory( product.OriginalProductID, true ), Region = src.Value.Region });? - TcKs
很棒的问题,因为我自己也一直在想。+1 - Kevin Le - Khnle
6
我发现 LINQ 中的“类似 SQL”的格式通常更难处理,虽然看起来更好看,但是它在使用自己的 Linq 提供程序时有问题,因为您无法控制所使用的关键字。在这种情况下,我只是使用简单的 Linq-to-objects,但是我在我的项目中也使用自定义的 Linq 提供程序。此外,“语法手术医生”感觉更像编写 VB 代码而不是 C# 代码。 - Aren
4个回答

27

我的格式:

var allInventory = system.InventorySources
  .Select(src => new
  {
    Inventory = src.Value.GetInventory(product.OriginalProductId, true),
    Region = src.Value.Region
  })
  .GroupBy(
    i => i.Region,
    i => i.Inventory
  );

注:

  • 方法的左括号从不值得换新行。
  • 右括号与包含左括号的行对齐。
  • src => new 保持在和 Select 同一行,因为它不值得另起一行。
  • 匿名类型始终像在查询之外使用时一样进行块处理(但右括号不应该另起一行)。
  • 通常不使用两个参数的 GroupBy 重载。虽然它可以轻松放在一行上,但多用一行可以清晰地表明发生了一些不寻常的情况。

1
就像我的一样。但是,如果写成 system.InventorySources.Select(src => src.Value.Region),你会将其写成单行还是分成多行以避免破坏缩进标准?这是我经常感到困惑的事情 :) 我知道这只是一个小问题,但仍然... - yakya
2
如果只有一个带有一个lambda的方法调用,并且它没有超过所需的行长度,我将把它保留为单行。 - Amy B
1
特别是关于你的第三条,我也喜欢它,因为它介绍了下面创建的内容以供使用该方法——它不属于新行,因为这会使其孤立。 - James D

14

我决定采用块格式。一开始,这种格式会让我觉得有些空间被浪费,但最终大家都觉得它更适合更多人阅读。因为我们已经将左右大括号放在了新的一行,所以这种格式也更符合代码的整体风格。而且,这种格式也不容易被误解。我们在公共存储区中保存了一个cs文件,其中包含格式示例...如果有人想到一个独特的Linq操作,我们就会将其添加到该文件中...真的对新人很有帮助。


是的,当考虑块格式时,我也有同样的想法,即“浪费空间”的因素,但它确实可以提高可读性。 - Aren

3
对于我来说,这取决于我需要查询的语句长度。对于简短的基本选择或简单连接语句,我会使用List Formatting,因为它使代码易于阅读,而不会使我的代码过多地占用行数。
如果我倾向于使用相当复杂或较大的linq语句,我会使用块格式化,以便其他人更容易阅读并跟踪我试图做什么。
我认为,针对不同语句使用不同的格式并没有不良实践,只要您在处理方式上保持一致即可。

0

这非常主观。

我使用块格式化方法。

我还会检查代码是否符合 Stylecop 的规范,并确保它不会产生任何 Stylecop 警告。


我知道这在某种程度上是主观的,但这就是为什么我希望人们能够提供格式背后的理由。 - Aren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接