-2

From previous experience, I had always thought that, if you are going to use variables inside of a for loop, it was much better to declare them outside of the loop vs. inside the loop itself. I recently had a code review done and had several younger developers claim that this was not true and that I should be putting my variables declarations inside the {} of the for loop.

Maybe compilers have just become more efficient, but it seems this would cause quite a number of memory releases/garbage collects since each iteration would be declaring a new instance of each variable, especially given that the majority of them are strings which are immutable.

2
  • @MichaelT For the first time in possibly ever, I completely agree with that dupe target.
    – Ixrec
    Commented Jan 4, 2016 at 0:32
  • The linked duplicate talks about trivial types (int). If you're talking about non-trivial types in your for loop, the results here be different but the suggestions in the linked topic are the same (try to compile the result and see what is generated).
    – Brandin
    Commented Jan 4, 2016 at 1:10

3 Answers 3

1

In the context of C#, it is hard to imagine how declaring the variable in one scope or another affects the garbage collection. In C# and Java, scope does not dictate storage reclamation (while on the other hand, it has implications in C++).

Local variables, in particular in C#, are mostly free. So, declaring one in an inner scope, even if looping is basically free.

It is possible that some initializer expression for something that could be reused (e.g. is unchanging) in the loop is more efficient when outside the loop, however, your question doesn't directly mention that, and seems to be concerned with the cost of the variables instead.

In general, we are better off to declare variables in the smallest scope possible. In general it is premature to consider performance before other factors, but in this case there is virtually no tension between performance and maintainable coding style.

1

It's worse than that, Jim ...

Since you tagged the question c#, you're not only wrong in assuming that there is any performance benefit (this is a trivial optimization, one any halfway-decent compiler will perform), but also in assuming that the declarations are re-executed on each loop pass. In fact, the variable will have space allocated for it at some point between entry into the loop and its first use, and will be freed sometime after its last use. In the case of a non-primitive variable (i.e., an object), only executing a new operator will actually cause the object to be created, regardless of where the variable is declared, and every new will create a new object, every time.

0

Generally you want to restrict the scope of your objects as much as possible. If your variable is only used inside the loop, and you do not require state to carry between iterations, then yes you usually want to declare it inside the loop so that each iteration contains a fresh variable.

Sometimes this carries performance penalties, as you suggest. I'd wager it's pretty rare, especially with modern optimising compilers, but it's still conceivable.

As always, the best advice I can give is to measure it if you think there's a problem. If you really need to, then fine move the declaration outside and be sure to "reset" the variable at the start of each iteration, if that's what turns out to be cheapest. Just be aware that your code will make slightly less sense to readers, so you need to write a comment to explain your choice (if for no other reason than to prevent future maintainers from undoing it) and be extra careful that you're not causing bugs.

So, were the younger developers right? Yes, in the main. But — as always — context rules.

2
  • "be aware that your code will make slightly less sense to readers" Why would it make less sense? "be extra careful that you're not causing bugs" What bugs? Commented Jan 4, 2016 at 1:59
  • 1
    @MichaelShaw: A variable that's outside of its appropriate scope makes less sense than a variable that's in the correct scope. And you could cause bugs by re-using an object without properly resetting it. For example, in C++, re-using a std::stringstream ss, clearing its buffer with ss.str("") but forgetting to clear its error flag state with ss.clear(). Subsequent operations on the stream may not have the desired (or any!) effect. I see it all the time. The best approach is to have a fresh ss each time and let the compiler worry about performance problems, optimising only if needed. Commented Jan 4, 2016 at 2:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.