代码之家  ›  专栏  ›  技术社区  ›  Jagd Dai

.NET中的性能和foreach循环

  •  0
  • Jagd Dai  · 技术社区  · 15 年前

    我有以下单击事件。

    protected void btnUpdate_Click(object sender, EventArgs e) {
            foreach (GridViewRow gvr in gvEditBulletins.Rows) {
                RadEditor re = (RadEditor)gvr.FindControl("reBulletin");
                DropDownList ddl = (DropDownList)gvr.FindControl("ddlPosition");
    
                // Business logic
            }
        }
    

    在每次迭代中声明一个radeditor和dropdownlist的实例后,我是否会受到性能上的影响,或者编译器是否足够聪明,能够知道如何重用这些实例?

    4 回复  |  直到 15 年前
        1
  •  2
  •   jason    15 年前

    首先,即使担心这是一个微优化;在研究应用程序的性能之前,您不应该担心这一点,分析表明此方法和此循环是瓶颈。其次,是的,编译器将重用本地变量的同一个实例 re ddl .

    下面是一个非常简单的例子:

    class Program {
        static void Main(string[] args) {
            string[] strings = new [] { "hello", "world" };
            foreach (string s in strings) {
                int i = s.Length;
            }
            return;
        }
    }
    

    这里是IL:

    .method private hidebysig static void Main(string[] args) cil managed {
        .entrypoint
        .maxstack 3
        .locals init (
            [0] string[] strings,
            [1] string s,
    --->    [2] int32 i,
            [3] string[] CS$0$0000,
            [4] string[] CS$6$0001,
            [5] int32 CS$7$0002,
            [6] bool CS$4$0003)
        L_0000: nop 
        L_0001: ldc.i4.2 
        L_0002: newarr string
        L_0007: stloc.3 
        L_0008: ldloc.3 
        L_0009: ldc.i4.0 
        L_000a: ldstr "hello"
        L_000f: stelem.ref 
        L_0010: ldloc.3 
        L_0011: ldc.i4.1 
        L_0012: ldstr "world"
        L_0017: stelem.ref 
        L_0018: ldloc.3 
        L_0019: stloc.0 
        L_001a: nop 
        L_001b: ldloc.0 
        L_001c: stloc.s CS$6$0001
        L_001e: ldc.i4.0 
        L_001f: stloc.s CS$7$0002
        L_0021: br.s L_0038
        L_0023: ldloc.s CS$6$0001
        L_0025: ldloc.s CS$7$0002
        L_0027: ldelem.ref 
        L_0028: stloc.1 
        L_0029: nop 
        L_002a: ldloc.1 
    --->L_002b: callvirt instance int32 [mscorlib]System.String::get_Length()
    --->L_0030: stloc.2
        L_0031: nop 
        L_0032: ldloc.s CS$7$0002
        L_0034: ldc.i4.1 
        L_0035: add 
        L_0036: stloc.s CS$7$0002
        L_0038: ldloc.s CS$7$0002
        L_003a: ldloc.s CS$6$0001
        L_003c: ldlen 
        L_003d: conv.i4 
        L_003e: clt 
        L_0040: stloc.s CS$4$0003
        L_0042: ldloc.s CS$4$0003
        L_0044: brtrue.s L_0023
        L_0046: br.s L_0048
        L_0048: ret 
    

    }

    注意,在局部变量部分,变量 i 声明为占用堆栈上的第二个位置,这是 get_Length 通过循环在每次迭代中重复存储。(我已经用 ---> S在页边。)

        2
  •  3
  •   Preet Sangha    15 年前

    它没有创建新实例( 除非在创建它们的控件上有自定义的显式强制转换运算符 )find会找到一个存在的对象并为您投射它。

        3
  •  0
  •   user113476    15 年前

    您不应该招致任何性能损失,因为这些控件应该已经存在于页面上。不然你怎么能找到他们?

        4
  •  0
  •   Mike Dunlavey    15 年前

    性能成功?你能每秒点击1000次按钮吗?如果是这样,它 可以 成为一个问题。