在 FOR 循环中声明变量 [英] Declaring variables within FOR loops

查看:80
本文介绍了在 FOR 循环中声明变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

生产中出现了一个奇怪的错误,我被要求调查.
问题被追溯到在 For 循环中声明的几个变量,并且没有在每次迭代时初始化.已经假设由于它们的声明范围,它们将被重置".在每次迭代中.
谁能解释为什么他们不会)?
(我的第一个问题,真的很期待回复.)
下面的例子显然不是有问题的代码,而是反映了场景:
请原谅代码示例,它在编辑器预览中看起来不错??

A weird bug was occurring in production which I was asked to look into.
The issue was tracked down to a couple of variables being declared within a For loop and not being initialized on each iteration. An assumption had been made that due to the scope of their declaration they would be "reset" on each iteration.
Could someone explain why they would not be)?
(My first question, really looking forward to the responses.)
The example below is obviously not the code in question but reflects the scenario:
Please excuse the code example, it looks fine in the editor preview??

for (int i =0; i< 10; i++)
{
    decimal? testDecimal;
    string testString;

    switch( i % 2  )
    {
        case 0:
        testDecimal = i / ( decimal ).32;
        testString = i.ToString();
            break;
        default:
            testDecimal = null;
            testString = null;
            break;
    }

    Console.WriteLine( "Loop {0}: testDecimal={1} - testString={2}", i, testDecimal , testString );
}


抱歉,因为育儿问题不得不赶出去.问题是 prod 代码的 switch 语句很大,并且在某些情况"中正在对类属性进行检查,例如 if (myObject.Prop != null) then testString = myObject.Stringval...在切换结束时,(外部)对 testString == null 进行了检查,但它保存了上次迭代的值,因此不像编码器在循环中声明变量时假定的那样为 null.
对不起,如果我的问题和例子有点不对,我接到了关于日托中心的电话,因为我正在把它放在一起.我应该提到我比较了循环内外两个变量的 IL.那么,是否普遍认为显然不会在每个循环中重新初始化变量"?
多一点信息,变量 WHERE 在每次迭代中都被初始化,直到有人对 ReSharper 表示从未使用过该值"过于热情为止.并删除它们.


Sorry, had to rush out for child care issue. The issue was that the prod code had was that the switch statement was huge and in some "case"'s a check on a class' property was being made, like if (myObject.Prop != null) then testString = myObject.Stringval... At the end of the switch, (outside) a check on testString == null was being made but it was holding the value from the last iteration,hence not being null as the coder assumed with the variable being declared within the loop.
Sorry if my question and example was a bit off, I got the phone call about the day care as I was banging it together. I should have mentioned I compared IL from both variables in and out the loop. So, is the common opinion that "obviously the variables would not be reinitialized on each loop"?
A little more info, the variables WHERE being initialized on each iteration until someone got over enthusiastic with ReSharper pointing out "the value is never used" and removed them.

各位,谢谢大家.作为我的第一篇文章,我看到我将来应该更加清晰.我们意外的变量分配的原因可以放在一个没有经验的开发人员身上,他做了 ReSharper 告诉他的所有事情,并且在他运行代码清理"之后没有运行任何单元测试.在整个解决方案上.在 VSS 中查看此模块的历史记录,我看到变量 Where 在循环外声明并在每次迭代时初始化.有问题的人希望他的 ReSharper 显示全绿色".所以将他的变量移近赋值"然后删除冗余分配"!我认为他不会再这样做了……现在花周末时间运行他错过的所有单元测试!
如何将问题标记为已回答?

Folks, I thank you all. As my first post I see how much clearer I should be in the future. The cause of our unexpected variable assignment can me placed on an inexperienced developer doing everything ReSharper told him and not running any unit tests after he ran a "Code Cleanup" on an entire solution. Looking at the history of this module in VSS I see variables Where declared outside of the loop and where initialized on each iteration. The person in question wanted his ReSharper to show "all green" so "moved his variables closer to assignment" then "Removed redundant assignment"! I don't think he will be doing it again...now to spend the weekend running all the unit tests he missed!
How to do mark a question as answered?

推荐答案

大多数,在循环内或循环外声明变量并不重要;明确分配的规则确保它无关紧要.在调试器中,您可能偶尔会看到旧值(即,如果您在分配之前在断点中查看变量),但静态分析证明这不会影响执行代码.每个循环都不会重置变量,因为显然没有必要.

Most of the time, it does not matter whether you declare a variable inside or outside the loop; the rules of definite assignment ensure that it doesn't matter. In the debugger you might occasionally see old values (i.e. if you look at a variable in a breakpoint before it is assigned), but static-analysis proves that this won't impact executing code. The variables are never reset per loop, as there is demonstrably no need.

在 IL 级别,**通常* 变量只为方法声明一次 - 循环内部的放置只是为了我们程序员的方便.

At the IL level, **usually* the variable is declared just once for the method - the placement inside the loop is just a convenience for us programmers.

然而有一个重要的例外;任何时候捕获一个变量,范围规则都会变得更加复杂.例如(2 秒):

HOWEVER there is an important exception; any time a variable is captured, the scoping rules get more complex. For example (2 secs):

        int value;
        for (int i = 0; i < 5; i++)
        {
            value = i;
            ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(value); });
        }
        Console.ReadLine();

非常不同的是:

        for (int i = 0; i < 5; i++)
        {
            int value = i;
            ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(value); });
        }
        Console.ReadLine();

因为第二个示例中的值"是每个实例真正,因为它被捕获.这意味着第一个示例可能会显示(例如)4 4 4 4 4",而第二个示例将显示 0-5(以任何顺序) - 即1 2 5 3 4".

As the "value" in the second example is truly per instance, since it is captured. This means that the first example might show (for example) "4 4 4 4 4", where-as the second example will show 0-5 (in any order) - i.e. "1 2 5 3 4".

那么:原始代码中是否涉及捕获?任何带有 lambda、匿名方法或 LINQ 查询的内容都符合条件.

So: were captures involved in the original code? Anything with a lambda, an anonymous method, or a LINQ query would qualify.

这篇关于在 FOR 循环中声明变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆