2008-12-18 26 views
1

我应该实例之内或之外我对循环请告诉我最有效的方式来实例化工人变量

例如我的工人变量

一个)

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而言。但对于可读性和清晰度的范围内......不如

+0

我曾经在外面做过,但ReSharper告诉我要在里面做。我会对人们的回复感兴趣 – 2008-12-18 15:12:50

+0

“bool b = default(bool)”非常古怪! – mackenir 2008-12-18 15:30:06

回答

1

以前的答案被删除,因为我会误读代码。 (使用“默认(布尔)”的任何地方是有点奇怪,顺便说一句。)

然而,除非该变量由委托等拍摄,我期望他们要么编译成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 

的唯一区别是其中的变量位于堆栈中。

0

我想声明它们的循环中,它节省了一行代码(声明,并将其设置在同一行),并且更容易看到什么我在循环范围之外使用的变量,当你在处理复杂的事情时这很好。

1

内部看起来比较清爽,但同意与Jon的IL将是相同的。

1

内。变量的范围应该根据实际使用情况而定。声明它在范围之外的变量包含块是不必要的,可能会导致混淆。

编辑:我猜测,这个代码只是为了说明的例子,但其实我省略了多余的变量,并把它写成:

for (int i = 0; i < MyCollection.Length; i++) 
{ 
    foreach(MyObjectClass myObject in myObjectCollection) 
    { 
     if (myObject.Property == MyCollection[i].Property) 
     { 
      DoSomethingWith(MyCollection[i]); 
      break; 
     } 
    } 
} 
0

声明变量尽可能靠近到你使用它们的第一个地方,让编译器担心生成最有效的IL(至少在这种情况下)。

0

另一点是范围。如果一个变量在一个循环之外声明,我应该期待它在循环之后被使用吗?这是我通常假设的。

0

编写代码与读者在你脑海的第一件事。应该优化代码中令人惊讶的一小部分代码。

通常在优化和可读性之间进行权衡。由于大部分人力资源都用于修改和编辑现有代码,因此通过正确的决策倾向于优化可读性。

80/20规则通常应用于此。

0

我同意siz,我依赖于范围,如果变量不是在除了循环内部以外的任何地方使用,然后在循环中声明它。如果要在循环结束后使用它,则需要在外部声明。

相关问题