1

forループの内側または外側でワーカー変数をインスタンス化する必要があります

例えば

a)

bool b = default(bool);

for (int i = 0; i < MyCollection.Length; i++)
{
  b = false;

  foreach(object myObject in myObjectCollection)
  {
    if (object.Property == MyCollection[i].Property)
    {
      b = true;
      break;
    }
  }      

  if (b)
  {
    DoSomethingWith(MyCollection[i]);
  }
}

b)

for (int i = 0; i < MyCollection.Length; i++)
{
  bool b = default(bool);

  foreach(object myObject in myObjectCollection)
  {
    if (object.Property == MyCollection[i].Property)
    {
      b = true;
      break;
    }
  }      

  if (b)
  {
    DoSomethingWith(MyCollection[i]);
  }
}

編集:ILが関係しているところでは違いがないことに普遍的に同意したようです。しかし、読みやすさと範囲の明確さのために...内部はより良いです

4

8 に答える 8

1

内部はきれいに見えますが、Jon に同意します。IL は同じになります。

于 2008-12-18T15:15:41.540 に答える
1

コードを読み間違えたため、以前の回答は削除されました。(どこでも "default(bool)" を使用するのは少し奇妙です。)

ただし、変数がデリゲートなどによってキャプチャされない限り、(動作とパフォーマンスの両方の点で) 実質的に同じ IL にコンパイルされることを期待します。

これまでと同様に、最も読みやすいコードを最初に記述します。このようなマイクロ最適化は、問題を引き起こしています。変数のスコープをできる限り制限することを提案した他の人たちに同意します。したがって、ループの後にそれが必要な場合は、とにかく選択肢がありません。それ以外の場合は、内部で宣言します。

さて、ここにテストプログラムがあります:

using System;

class Test
{
    static void Main() {}

    static void DeclareInside()
    {
        for (int i=0; i < 10; i++)
        {
            bool x = false;
            for (int j=5; j < 20; j++)
            {
                if (i == j)
                {
                    x = true;
                    break;
                }
                if (x)
                {
                    Console.WriteLine("Yes");
                }
            }
        }
    }

    static void DeclareOutside()
    {
        bool x;
        for (int i=0; i < 10; i++)
        {
            x = false;
            for (int j=5; j < 20; j++)
            {
                if (i == j)
                {
                    x = true;
                    break;
                }
                if (x)
                {
                    Console.WriteLine("Yes");
                }
            }
        }
    }
}

生成された IL (ちょうどcsc Test.cs):

.method private hidebysig static void  DeclareOutside() cil managed
{
  // Code size       79 (0x4f)
  .maxstack  2
  .locals init (bool V_0,
           int32 V_1,
           int32 V_2,
           bool V_3)
  IL_0000:  nop
  IL_0001:  ldc.i4.0
  IL_0002:  stloc.1
  IL_0003:  br.s       IL_0045
  IL_0005:  nop
  IL_0006:  ldc.i4.0
  IL_0007:  stloc.0
  IL_0008:  ldc.i4.5
  IL_0009:  stloc.2
  IL_000a:  br.s       IL_0037
  IL_000c:  nop
  IL_000d:  ldloc.1
  IL_000e:  ldloc.2
  IL_000f:  ceq
  IL_0011:  ldc.i4.0
  IL_0012:  ceq
  IL_0014:  stloc.3
  IL_0015:  ldloc.3
  IL_0016:  brtrue.s   IL_001d
  IL_0018:  nop
  IL_0019:  ldc.i4.1
  IL_001a:  stloc.0
  IL_001b:  br.s       IL_0040
  IL_001d:  ldloc.0
  IL_001e:  ldc.i4.0
  IL_001f:  ceq
  IL_0021:  stloc.3
  IL_0022:  ldloc.3
  IL_0023:  brtrue.s   IL_0032
  IL_0025:  nop
  IL_0026:  ldstr      "Yes"
  IL_002b:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0030:  nop
  IL_0031:  nop
  IL_0032:  nop
  IL_0033:  ldloc.2
  IL_0034:  ldc.i4.1
  IL_0035:  add
  IL_0036:  stloc.2
  IL_0037:  ldloc.2
  IL_0038:  ldc.i4.s   20
  IL_003a:  clt
  IL_003c:  stloc.3
  IL_003d:  ldloc.3
  IL_003e:  brtrue.s   IL_000c
  IL_0040:  nop
  IL_0041:  ldloc.1
  IL_0042:  ldc.i4.1
  IL_0043:  add
  IL_0044:  stloc.1
  IL_0045:  ldloc.1
  IL_0046:  ldc.i4.s   10
  IL_0048:  clt
  IL_004a:  stloc.3
  IL_004b:  ldloc.3
  IL_004c:  brtrue.s   IL_0005
  IL_004e:  ret
} // end of method Test::DeclareOutside

.method private hidebysig static void  DeclareInside() cil managed
{
  // Code size       79 (0x4f)
  .maxstack  2
  .locals init (int32 V_0,
           bool V_1,
           int32 V_2,
           bool V_3)
  IL_0000:  nop
  IL_0001:  ldc.i4.0
  IL_0002:  stloc.0
  IL_0003:  br.s       IL_0045
  IL_0005:  nop
  IL_0006:  ldc.i4.0
  IL_0007:  stloc.1
  IL_0008:  ldc.i4.5
  IL_0009:  stloc.2
  IL_000a:  br.s       IL_0037
  IL_000c:  nop
  IL_000d:  ldloc.0
  IL_000e:  ldloc.2
  IL_000f:  ceq
  IL_0011:  ldc.i4.0
  IL_0012:  ceq
  IL_0014:  stloc.3
  IL_0015:  ldloc.3
  IL_0016:  brtrue.s   IL_001d
  IL_0018:  nop
  IL_0019:  ldc.i4.1
  IL_001a:  stloc.1
  IL_001b:  br.s       IL_0040
  IL_001d:  ldloc.1
  IL_001e:  ldc.i4.0
  IL_001f:  ceq
  IL_0021:  stloc.3
  IL_0022:  ldloc.3
  IL_0023:  brtrue.s   IL_0032
  IL_0025:  nop
  IL_0026:  ldstr      "Yes"
  IL_002b:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0030:  nop
  IL_0031:  nop
  IL_0032:  nop
  IL_0033:  ldloc.2
  IL_0034:  ldc.i4.1
  IL_0035:  add
  IL_0036:  stloc.2
  IL_0037:  ldloc.2
  IL_0038:  ldc.i4.s   20
  IL_003a:  clt
  IL_003c:  stloc.3
  IL_003d:  ldloc.3
  IL_003e:  brtrue.s   IL_000c
  IL_0040:  nop
  IL_0041:  ldloc.0
  IL_0042:  ldc.i4.1
  IL_0043:  add
  IL_0044:  stloc.0
  IL_0045:  ldloc.0
  IL_0046:  ldc.i4.s   10
  IL_0048:  clt
  IL_004a:  stloc.3
  IL_004b:  ldloc.3
  IL_004c:  brtrue.s   IL_0005
  IL_004e:  ret
} // end of method Test::DeclareInside

唯一の違いは、変数がスタック内のどこにあるかです。

于 2008-12-18T15:16:39.773 に答える
1

中身。変数のスコープは、実際の使用に限定する必要があります。変数をスコープ外で宣言すると、含まれているブロックに変数が渡されますが、これは不要であり、混乱を招く可能性があります。

編集:このコードは例を説明するためのものだと推測していますが、実際には無関係な変数を省略して次のように記述します。

for (int i = 0; i < MyCollection.Length; i++)
{
   foreach(MyObjectClass myObject in myObjectCollection)
   {
        if (myObject.Property == MyCollection[i].Property)
        {
             DoSomethingWith(MyCollection[i]);
             break;
        }
   }
}
于 2008-12-18T15:18:22.907 に答える
0

私はそれらをループ内で宣言するのが好きで、コード行を節約し (同じ行で宣言して設定するため)、ループのスコープの外側と内側で使用している変数を簡単に確認できます。これは良いことです。複雑な作業をしている時。

于 2008-12-18T15:14:08.857 に答える
0

変数を最初に使用する場所のできるだけ近くで変数を宣言し、コンパイラに最も効率的な IL の生成について心配させます (この場合は少なくとも)。

于 2008-12-18T15:18:30.003 に答える
0

もう1つのポイントはスコープです。変数がループの外側で宣言されている場合、ループの後に使用されることを期待する必要がありますか? それが私が通常想定していることです。

于 2008-12-18T15:19:43.870 に答える
0

リーダーのことを第一に考えてコードを書きます。コードの驚くほど小さな部分を最適化する必要があります。

多くの場合、最適化と読みやすさの間にはトレードオフがあります。マンパワーのほとんどは既存のコードの修正と編集に費やされているため、通常、最適化よりも読みやすさを重視するのが正しい決定です。

ここでは 80/20 ルールがよく適用されます。

于 2008-12-18T15:23:37.780 に答える
0

サイズに同意します。スコープによって異なります。変数がループ内以外の場所で使用されない場合は、ループ内で宣言します。ループが終了した後に使用する場合は、外部で宣言する必要があります。

于 2008-12-18T15:25:52.627 に答える