23

次の例では:

  • 最初のものはより冗長に見えますが、リソースの浪費は少ないです
  • 2つ目は、冗長性は低くなりますが、リソースの浪費になります(各ループの文字列を再定義します)

どちらがより良いコーディング慣行ですか?

最初の例:

using System;
using System.Collections.Generic;

namespace TestForeach23434
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> names = new List<string> { "one", "two", "two", "three", "four", "four" };

            string test1 = "";
            string test2 = "";
            string test3 = "";
            foreach (var name in names)
            {
                test1 = name + "1";
                test2 = name + "2";
                test3 = name + "3";
                Console.WriteLine("{0}, {1}, {2}", test1, test2, test3);
            }
            Console.ReadLine();
        }
    }
}

2番目の例:

using System;
using System.Collections.Generic;

namespace TestForeach23434
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> names = new List<string> { "one", "two", "two", "three", "four", "four" };

            foreach (var name in names)
            {
                string test1 = name + "1";
                string test2 = name + "2";
                string test3 = name + "3";
                Console.WriteLine("{0}, {1}, {2}", test1, test2, test3);
            }
            Console.ReadLine();
        }
    }
}
4

12 に答える 12

46

2番目の形式はもはや無駄ではありません-それは単により良いです。

反復間で変数の値を維持したい場合を除いて、ループの外側で変数を宣言することに利点はありません。

通常、これによって動作に違いはありませんが、変数がラムダ式または無名メソッドによってキャプチャされている場合はそうではないことに注意してください。)

于 2010-03-05T17:28:13.793 に答える
18

個人的には、変数の使用法を考えると、可能な限り狭い範囲で変数を宣言することがベストプラクティスだと思います。

これには多くの利点があります。

  1. 変数がすでに同じスコープにある場合、メソッドの抽出が簡単になるため、リファクタリングが簡単になります。
  2. 変数の使用法がより明確になり、コードの信頼性が高まります。

唯一の(潜在的な)欠点は、余分な変数宣言です。ただし、JITはこの問題を最適化する傾向があるため、実際の作業では必ずしも心配する必要はありません。

これに対する1つの例外:

変数が大量のGC圧力を追加する予定であり、foreach / forループを介して同じオブジェクトインスタンスを再利用することでこれを回避できる場合、およびGC圧力が測定されたパフォーマンスの問題を引き起こしている場合は、それを持ち上げます外側のスコープ。

于 2010-03-05T17:29:49.503 に答える
5

それらは無駄で冗長です。

foreach (var name in names)
{
   Console.WriteLine("{0}1, {0}2, {0}3", name);
}

</tongueincheek>
于 2010-03-05T17:27:46.963 に答える
2

言語とコンパイラに応じて、同じ場合と同じでない場合があります。C#の場合、結果のコードは非常に似ていると思います。

これに関する私自身の哲学は単純です:

理解しやすいように最適化します。

それ以外は時期尚早の最適化です!ほとんどの開発における最大のボトルネックは、開発者の時間と注意です。最後のCPUサイクルごとにどうしても絞り出さなければならない場合は、必ずそうしてください。ただし、やむを得ないビジネス上の必要がある場合や、重要なコンポーネント(共通ライブラリ、オペレーティングシステムカーネルなど)を作成している場合を除いて、完成したプログラムのベンチマークを行うことができます。その時点で、最もコストのかかるルーチンのいくつかを最適化することは正当化されます。それ以前は、ほぼ確実に時間の無駄です。

于 2010-03-05T17:32:19.787 に答える
1

ループの外側で文字列変数を定義することで何が得られるかわかりません。文字列は不変であるため、再利用されません。それらに割り当てるたびに、新しいインスタンスが作成されます。

于 2010-03-05T17:29:08.323 に答える
0

何を解決しようとしているのかによると思います。コードを1つのステップで移動できるため、2番目の例が好きです。最初の例が好きです。スタック操作が少なく、メモリの断片化が少なく、オブジェクトの構築/作成が少ないため、高速です。

于 2010-03-05T17:29:22.397 に答える
0

ループからの「巻き上げ」宣言は、通常、保守のためのより優れた長期戦略であることがわかりました。コンパイラーは通常、パフォーマンスのために許容範囲内で物事を整理します。

于 2010-03-05T17:30:23.573 に答える
0

パフォーマンスに関してはどちらも実質的に同じですが(文字列は不変です)、読みやすさに関しては...どちらも非常に優れているとは言えません。Console.WriteLine内ですべてを簡単に行うことができます。

おそらく、例の代わりに実際の問題を投稿できますか?

于 2010-03-05T17:36:25.740 に答える
0

私は通常、スコープが許す限り変数の使用に近いと宣言します。この場合、これが2番目の例になります。Resharperはこのスタイルも奨励する傾向があります。

于 2010-03-05T18:22:46.053 に答える
0

PODタイプのデータの場合、最初の使用に最も近いと宣言します。メモリ割り当てを行うクラスのようなものについては、ループの外側でそれらを宣言することを検討する必要があります。文字列はほぼ確実に何らかの形の割り当てを行い、ほとんどの実装(少なくともC ++では)は可能であればメモリの再利用を試みます。ヒープベースの割り当ては、実際には非常に遅くなる可能性があります。

私はかつて、ctorにデータを新しく追加するクラスを含むC++コードのプロファイルを作成しました。ループの外側で宣言された変数を使用すると、ループの内側で宣言された変数を使用した場合よりも17%速く実行されました。YMMVはC#であるため、プロファイルのパフォーマンスは結果に非常に驚かれる可能性があります。

于 2010-03-05T19:38:38.357 に答える
0

これはLinqの私のお気に入りの部分であり、ここに収まると思います。

names.ForEach(x => Console.WriteLine("{0}1, {0}2, {0}3", x));
于 2016-10-21T11:27:21.297 に答える
-1

変数を宣言するときは、簡単なルールに従ってください

初めて必要になったときに宣言する

于 2010-03-05T17:31:35.817 に答える