web-dev-qa-db-ja.com

ReSharperがforループをLINQ式に変換することを提案するのはなぜですか?

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 + ">";
    }
}
24
CSharpened

コードの大部分では速度が無関係であることがよくあります。コードを最も単純なの方法で記述し、それを測定して十分に速いであることを確認する必要があります。

Forループが本当にクエリを実行しているだけの場合、LINQは絶対により読みやすいコードを作成するための優れた方法です。それは普遍的に適用できるわけではありませんが、少なくとも覚えておいてください頻繁にすべきことです。

多くの場合、forループをクエリに変換して遅延評価し、クエリによって返された各値に対して何らかのアクションを実行するforeachループを作成できます。これにより、2つの側面を分離し、コードを読むときに一度に1つずつ集中できるようになります。ただし、LINQクエリを保持することは重要ですasクエリ内で副作用を使用するのではなく、機能的なアプローチを持つように設計されていますが、実際には副作用とうまく混ざりません。

具体的な例があれば、LINQを使用するように変換するのに意味のあるループとそうでないループについて、より多くの意見を述べることができます。

36
Jon Skeet

そのようなパフォーマンスの向上はありませんが、いくつかの利点があります

  • コードを読みやすくします。
  • 行数を減らします。
  • メンテナンスが簡単。
  • 場合によっては、forループで必要になる可能性のある一時変数が必要ありません。 Linqを使用すると、クエリを連鎖させることができます。

詳細については、以下を参照してください。

これがお役に立てば幸いです。

16
Amar Palsapure

速度に違いはない可能性がありますが、Linqを使用するとコードが簡潔になることがよくあります。これは、Linq式に変換するためのR#の提案を常に受け​​入れる必要があるということではありません。複雑であるが理解できるforeachループが、有効であるが簡単には理解できないLinq式に変換されることがあります。

4
Phil

たまに改宗しないのには理由があると思います。 ReSharperがLINQ式(戻る)をforループに変換するためのリファクタリングを提供しないことはおそらくあまり称賛に値しません。ループを式に変換した後、ループ内にさらにいくつかのアクション(多くの場合デバッグアクション)を入れたいと思ったことが何度かありました。手作業で元に戻す必要があります。

正当な理由なしにforループを変換しないように警告します。多くの場合、それは実際には読みやすさを改善せず、それを行う他の強力な理由はありません(他の人が正しく指摘しているように、ほとんどのループは速度が重要ではありません)。

一部のforループは、ループのアクションを一口サイズの断片に視覚的に分解するため、LINQの同等のものよりも読みやすいと思います。小さなループ(3行または4行)が1行の式にすることで最も改善される傾向があると思います。

[申し訳ありませんが、この投稿はほとんど意見ですが、読みやすさは少し主観的な主題です。トローリングなし!]

4
debater

一般に、ReSharperの提案は単なる提案であり、警告はありません。したがって、LINQまたはforeachのどちらに進むかを決めるのは、あなた次第です。
「Use'var '」という提案でも同じ問題が発生します。読者がステートメントをよりよく読むことができると思う場合にのみ、その提案をクリックします。
コードを書くときの読みやすさは私の最優先事項の1つです。

4
brgerner

こんにちはLinqは実際に内部でforループを呼び出しています。 Linq式は、一般的に読みやすく、保守しやすいということになると思います。パフォーマンスが本当に心配な場合は、2つの間に良い比較があります: http://geekswithblogs.net/BlackRabbitCoder/archive/2010/04/23/c-linq-vs-foreach---round- 1.aspx

2
skub

他の人への参照として、Resharperによって提案されたforループと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クエリはよりクリーンで読みやすく、行数が少なくなっています(この場合、コードは1行だけで、ここに貼り付けた後で調整しました)。デバッグも簡単です。

0
Willy David Jr