変数が使用される場所の近くで宣言するのはなぜですか?


10

変数はできる限り使用に近い場所で宣言する必要があると人々が言うのを聞いたことがあります。分かりません。

たとえば、このポリシーでは、これを行う必要があることを示唆しています。

foreach (var item in veryLongList) {
  int whereShouldIBeDeclared = item.Id;
  //...
}

しかし、これは確かに新しいintものを作成するオーバーヘッドがすべての反復で発生することを意味します。使用した方がいいでしょう:

int whereShouldIBeDeclared;
foreach (var item in veryLongList) {
  whereShouldIBeDeclared = item.Id;
  //...
}

誰か説明してもらえますか?


3
これら2つのケースを異なる方法で処理したのは、かなりひどい貧しい言語でしょう。
ポールトンブリン

5
あなたは誤った前提から始まります。この質問に私の答えをご覧ください。stackoverflow.com/questions/6919655/...
CesarGon

8
そのように考えると、一般的にパフォーマンスへの影響を最適化したり検討したりするのに適していません。言語の実装はスマートであり、そうでない場合は、公平で現実的なベンチマークを通じて取得したハードデータでそれを証明してください。

4
場合の2つのコード例は、重要な意味上の違いがあり、それらは異なることを行います。あなたがやりたいことをするものを使うべきです。変数を宣言する場所に関するルールは、意味的に違いがない場合にのみ適用されます。
David Schwartz

4
スケールの反対側を検討してください-すべてがグローバル変数です。確かに、「ほぼ宣言された使用法」がこの範囲のより良い終わりですか?
JBRウィルキンソン、2011年

回答:


27

これは多くのスタイルルールの1つであり、考えられるすべての可能なルールの中で最も重要なルールであるとは限りません。あなたの例は、intを含んでいるので、非常に魅力的ではありませんが、そのループ内に構築するのにコストのかかるオブジェクトがあり、ループの外側でオブジェクトを構築するための良い議論になる可能性があります。ただし、これはこのルールに対する良い議論にはなりません。最初に、ループ内で高価なオブジェクトを構築する必要のない他の場所がたくさんあり、次に、優れたオプティマイザ(そしてC#なので、優れたオプティマイザがあるので)ループの外に初期化を上げることができます。

このルールの本当の理由は、それがルールである理由が見えない理由でもあります。人々は何百、何千行もの関数を書いていて、Visual Studioが提供するようなサポートなしにプレーンテキストエディター(メモ帳など)で書いていたものです。その環境では、変数が使用されている場所から数百行離れた場所で変数を宣言すると、

if (flag) limit += factor;

フラグ、リミット、ファクターについての手がかりはあまりありませんでした。これを支援するために、ハンガリーの表記法のような命名規則が採用され、使用される場所に近いものを宣言するような規則も採用されました。もちろん、最近はリファクタリングがすべてであり、関数は一般に1ページよりも短いため、宣言されている場所と使用されている場所との間の距離を大きく取ることが難しくなっています。あなたは0から20の範囲で動作していて、この特定の例ではおそらく7で大丈夫ですが、ルールを作った人は7行離れるのが大好きで、700から誰かと話をしようとしていました。その上、Visual Studioでは、何にでもマウスを合わせてその型を確認したり、メンバー変数にしたりできます。つまり、それを宣言する行を見る必要性が少なくなります。

それはまだかなり良いルールであり、最近では破ることが非常に難しいものであり、遅いコードを書く理由として誰も主張しなかったものです。何よりも賢明である。


ご回答有難うございます。しかし、確かにデータ型に関係なく、新しいインスタンスはどの方法で作成しても毎回作成されますか?2番目のケースでは、毎回新しいメモリ参照を要求しないというだけです。または私は要点を逃しましたか?とにかく、C#オプティマイザがコンパイル時にコードを自動的に改善すると言っていますか?知らなかった!
James

2
intを作成するオーバーヘッドはごくわずかです。複雑なものを構築する場合、オーバーヘッドはより大きな問題になります。
ケイトグレゴリー

17
その種類などがわかるだけではありません。それは生涯の問題でもあります。変数「wibble」が最初に使用される前に30行と宣言されている場合、「wibble」を誤って使用するとバグが発生する可能性がある行が30行あります。使用する直前に宣言されている場合、前の30行で「wibble」を使用してもバグにはなりません。代わりにコンパイラエラーが発生します。
Mike Sherrill 'Cat Recall'

この場合、ループごとに新しいインスタンスが作成されるわけではありません。単一のトップレベル変数が作成され、反復ごとに使用されます(ILを見てください)。しかし、それは実装の詳細です。
thecoop、2011年

「Visual Studioでは、何にでもマウスを置いて見ることができます」などF12。必須のショートカットを備えた定義へのナビゲートもあります。
StuperUser

15

ループ内で変数を定義すると、そのループにのみローカルで可視になります。これには、読者にとって少なくとも3つの利点があります。

  1. 変数の定義と関連するコメントは見つけやすい
  2. 読者は、この変数が他の場所では使用されないことを知っています(期待する依存関係はありません)。
  3. コードを記述または編集するときに、ループの外で同じ変数名を使用してその変数を参照することはできません。そうしないと、エラーが発生する可能性があります。

効率ビットに関しては、コンパイラーは、生成された最適化されたコードのループの外で定義を生成するのが賢明です。変数はループの繰り返しごとに作成されるわけではありません。


4

人々は彼らの使用法に可能な限り近いと言います、彼らはあなたが常にそれをしなければならない必要があると言っているのではありません、なぜならそれらは最小スコープで変数を宣言することがいくつかのオーバーヘッドを引き起こすからです。そのステートメントの主な理由は読みやすさと変数を与えることですあなたができる最小のスコープ。


4

読みやすさには役立ちますが、この場合、読みやすさは主な考慮事項ではありません。また、最近のIDEはこのルールの必要性を未然に防ぎません。

主な問題は、初期化されていない変数です。変数を初期化から離れすぎて宣言すると、あらゆる種類の潜在的な問題が発生します。以前にRAMにあったもの、または関数の上位の計算の結果、またはコンパイラーが不平を言わないようにするために誰かが入れたダミー初期化(0など)の結果を誤って処理していることに気付くかもしれません。人々は、その変数の暗黙の前提条件を意識せずに、宣言と使用の間にコードを挿入します。最悪の場合、その使用法はたまたまテストでは機能しますが、フィールドでは失敗します。

できるだけ小さなスコープで変数を宣言し、宣言の時点で変数を適切な値に初期化することで、多くのメンテナンスの問題を回避できます。読みやすさの向上を強制するという事実は、ただ良い副作用です。


1

「必須」ではありません。それは単なる意見であり、私が何かをする方法です。たとえば、メソッドの最初の行ですべての変数を宣言して、その変数を使用して何をするかコメントできるようにします(もちろん、カウンターでない限り)。他の人々は、あなたが聞いたように、(あなたが書いた2番目の例のように)彼らを彼らの使用法のできるだけ近くに置きたいと思っています。とにかく、最初に提供する例は確かに「エラー」です(理解するとオーバーヘッドが発生するという意味で)。

あなたは単にあなたの方法を選択し、それに従ってください。


2
そうではありませんちょうどそれは、意見?ソフトウェアエンジニアリングの調査では、少なくとも1980年代以降のライブ時間とバグ数の関係を記録していませんか?
Mike Sherrill 'Cat Recall'

1

2つの例は機能的に異なるコードであり、互換性はありません。(取り除いた例では、違いはありませんが、重要なコードでは違いがあります)。サイトのルールは、「可能な限り」で示されているように、常にスコーピングの考慮事項に従います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.