5

C# コードでは、次の規則をよく見かけます。

some_type val;
val = something;

お気に入り

DataTable dt;
dt = some_function_returning_datatable();

また

DataTable dt = new DataTable();
dt = some_function_returning_datatable();

それ以外の

some_type val = something;
DataTable dt = some_function_returning_datatable();

これは、スコープの先頭ですべてのローカル変数を宣言しなければならなかった時代からの習慣だと最初は思っていました。しかし、私は、ベテラン開発者の習慣をすぐに却下してはならないことを学びました。

dt(私の 3 番目のコード セクションでは、最初に関数を割り当ててから関数から割り当てても、メモリの無駄にはなりませんnew)

では、1 行で宣言し、後で代入する正当な理由はありますか?

4

5 に答える 5

18

私の 3 番目のコード セクションでは、dt を最初に new で割り当て、次に関数から割り当てても、メモリの無駄にはなりません。

はい、そうなるでしょう。役に立たないDataTableオブジェクトを作成するという比較的マイナーなものですが、それでも無駄不明確です。

では、1 行で宣言し、後で代入する正当な理由はありますか?

値がすぐに得られない場合のみ。例えば:

string x;
if (someCondition) {
    // Do some work
    x = someResult;
} else {
    // Do some other work
    x = someOtherResult;
}

多くの場合、これは条件演算子を使用するか、そのコードをメソッドに抽出することで改善できます。それでもうまくいかないこともあります。

次の単純な状況の場合:

Foo x = SomeInitializationWithNoUsefulSideEffects();
x = SomeUsefulValue();

または

Foo x;
x = SomeUsefulValue();

絶対にリファクタリングする必要があります

Foo x = SomeUsefulValue();

宣言ポイントが違いを生むもう 1 つの興味深い状況は、キャプチャされた変数にありますが、通常は意図した方法ではありません。

int x;
for (int i = 0; i < 10; i++) {
    x = SomeFunction();
    actions.Add(() => Console.WriteLine(x));
}

for (int i = 0; i < 10; i++) {
    int x = SomeFunction();
    actions.Add(() => Console.WriteLine(x));
}

最初のスニペットでは、各デリゲートが同じ変数をキャプチャするため、すべてのデリゲートが から返された最後の値を効率的に確認できますSomeFunction2 番目のスニペットでは、各デリゲートが の個別の「インスタンス」をキャプチャしますx

于 2012-05-08T10:38:19.500 に答える
9

しかし、私は、ベテラン開発者の習慣をすぐに却下してはならないことを学びました。

心配したり、躊躇したりせずに、すぐにそれらを却下してください。C# で記述してもまったく意味がありません。

some_type val;
val = something;

それ以外の:

some_type val = something;

また:

DataTable dt = new DataTable();
dt = some_function_returning_datatable();

それ以外の:

DataTable dt = some_function_returning_datatable();

とにかく、コードでそれらを無視しない場合、C# コンパイラは結果の IL を発行するときにそれらを無視します。

于 2012-05-08T10:37:03.997 に答える
0

コードを読むとき、どの変数がスコープ内で変更され、どの変数が変更されないかを知ることは非常に役立ちます。これを大まかに示す便利な規則は、変数の値がスコープ全体で一定のままである場合は宣言と同じ行で変数を初期化し、両方の場合は宣言とは別の行で変数を初期化することです。

  1. その値はそのスコープ内で再割り当てされます。
  2. その事実はすぐにはわからないだろう

何かが「すぐに明らか」であるかどうかに関しては、判断の余地があります。適格となるいくつかの状況は次のとおりです。

  1. 明らかに定数値である何かへの変数の初期化 (特にそれが型のデフォルト値である場合)
  2. 定義の数行内での値の再割り当て
  3. 変数の名前と初期化式は、ループの初期化を示唆しています (例: "var currentFoo = firstFoo;")。

変数のスコープが長くなればなるほど、値が変更される場合に個別の初期化と宣言を使用する可能性が高くなります。

于 2012-05-24T17:41:14.230 に答える
0
SomeType someVar;
someVar = new(SomeType);

SomeType someVar = new(SomeType);

同等です。開発者の習慣かもしれません。分割が必要だったのにリファクタリングされたが、完全ではなかったのかもしれません。

SomeType someVar = new(SomeType);
someVar = GetSomeTypeFromSomewhereElse();

最初のインスタンスが明らかに何もせずに範囲外になるという点で、せいぜい非効率的なコーディングです。コンストラクターの副作用に依存するコース。いくつかある場合は、査読中に長くてつらいおしゃべりをすることになります。:D

その後、他の人が言ったsomeVarように、宣言する必要があるため、さらにロジックを介して割り当てることができます。

于 2012-05-08T11:02:14.727 に答える
0

それは各自の願いです。パフォーマンスの問題はありません。CLR は、1 行でも 2 行でも、どのように宣言しても独自の宣言を行うためです。

いつもフォローしてます

int i=5;

可能な限り。

ただし、 int i=5; を宣言するときは、必ず確認してください。1 行で、CLR は整数の新しいインスタンスを作成する必要があります。

于 2012-05-08T10:40:57.707 に答える