为什么ReSharper建议我将for循环转换为LINQ表达式?

时间:2012-02-14 09:20:52

标签: c# linq for-loop resharper

在Visual Studio中,Re-Sharper一直建议我将for循环转换为linq表达式,但这是什么原因?

哪个更快?

以下是一些示例循环,其中resharper建议使用linq转换:

foreach (XmlNode legendEntryNode in _legendEntryNodes)
{
    var xmlElement = legendEntryNode["FeatureType"];

    if (xmlElement == null || !xmlElement.InnerText.Equals(featuretype)) continue;

    var xmlNodeList = legendEntryNode.SelectNodes("Themes/Theme");

    if (xmlNodeList != null)

    foreach (XmlNode themeNode in xmlNodeList)
    {
        var element = themeNode["Value"];

        if (element == null || !element.InnerText.Equals(v)) continue;

        var xmlElement1 = themeNode["Icon"];

        if (xmlElement1 != null)
        {
            string iconname = "<ms:ICON>" + xmlElement1.InnerText + "</ms:ICON>";

            var element1 = themeNode["Highlight"];

            if (element1 != null)
            {
                string highlightname = "<ms:HIGHLIGHT>" + element1.InnerText + "</ms:HIGHLIGHT>";
                gml = gml.Insert(c, iconname + highlightname);

                c += (iconname.Length + highlightname.Length);
            }
        }
        break;
    }
}

这个更简单的例子:

for (int i = 0; i < getPointsRequest.Attribs.Length; i++)
{
    string attribName = getPointsRequest.Attribs[i].AttributeName;

    if (!String.IsNullOrEmpty(attribName))
    {
        sqlQuery += "<ms:" + attribName + ">||\"" + attribName + "\"||</ms:" + attribName + ">";
    }
}

7 个答案:

答案 0 :(得分:36)

速度通常与代码的大部分内容无关 - 您应该使用最简单的方式编写代码,然后对其进行测量以确保足够快

如果你的for循环真的只是查询,那么LINQ 绝对是一个结束更可读代码的好方法。它不是普遍适用的,但它应该至少牢记

通常可以将for循环转换为懒惰评估的查询,然后是foreach循环,对查询返回的每个值执行一些操作。这可以帮助区分这两个方面,让您在阅读代码时一次关注一个方面。将LINQ查询保留为查询非常重要,而不是在其中使用副作用 - 它的设计目的是提供一种功能性方法,它实际上不会与副作用混合得很好。

如果你有一些具体的例子,我们可以提供更多关于转换为使用LINQ哪些循环有意义的意见,哪些不会。

答案 1 :(得分:15)

没有性能提升,但有一些好处

  • 使代码更具可读性。
  • 减少行数。
  • 易于维护。
  • 在某些情况下,您不需要临时变量,在循环中可能需要这些变量。使用Linq,您可以链接查询。

有关详细信息,请参阅:

希望这会对你有所帮助。

答案 2 :(得分:4)

速度可能没有差别,但是使用Linq通常会产生更严格的代码。 这并不是说你应该总是接受R#的转换为Linq表达式的建议。有时复杂但可理解的foreach循环被转换为有效但不易理解的Linq表达式。

答案 3 :(得分:3)

一般来说,ReSharper的建议只是建议而非警告。因此,只有你自己决定走哪条路:LINQ或foreach 我有同样的问题,建议“使用'var'”。只有当我认为读者能够更好地阅读声明时,我才会点击该建议 在编写代码时,可读性是我的首要任务之一。

答案 4 :(得分:3)

我会说有时候不转换的原因。 ReSharper不提供将LINQ表达式(返回)转换为for循环的重构可能不太令人钦佩。我有几次将一个循环转换为一个表达式,然后又想在循环中放入一些进一步的动作(通常是调试动作);我必须手工转换它们。

我会警告不要在没有充分理由的情况下转换for循环。通常它确实没有提高可读性,并且没有任何其他强有力的理由去做(正如其他人正确指出的那样,大多数循环不是速度关键的。)

我认为一些for循环比LINQ等价物更易读,因为它们可以直观地将循环的动作分解为一口大小的碎片。我会说它往往是小循环(三行或四行),通过将它们变成一行中的表达式而得到最大改善。

[对不起这篇文章主要是意见,但可读性有点主观。没有拖钓!]

答案 5 :(得分:2)

Hi Linq实际上是在内部调用for循环。我想Linq表达式通常更易于阅读/维护。如果你真的关心性能,那么两者之间有一个很好的比较:http://geekswithblogs.net/BlackRabbitCoder/archive/2010/04/23/c-linq-vs-foreach---round-1.aspx

答案 6 :(得分:0)

作为其他人的参考,这里是一个for循环的示例和Resharper建议的for循环

for (int x = 0; x < grid.Length; x++)
        {
            var intCount = grid[x].Select((a, b) => new {Value = a, Index = b})
                .GroupBy(y => y.Value)
                .Where(y => y.Count() > 1).Select(item => item.Key).ToArray();

            if (intCount.Count() > 1)
                return false;
        }

为了解释这段代码,这个for循环将获得一个数组上的所有重复项。获取所有重复项后,检查项目数是否大于1,然后返回false。

这是LINQ中建议的for循环:

  return grid.Select(t => t.Select((a, b) => new {Value = a, Index = b}).
            GroupBy(y => y.Value).Where(y => y.Count() > 1).
            Select(item => item.Key).ToArray()).All(intCount => intCount.Count() <= 1);

可能没有性能提升,但正如您从示例中看到的那样,LINQ查询更干净,易于阅读,线条较少(在这种情况下,只有一行代码,我只是在粘贴后对其进行了调整)这里也很容易调试。