Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have heard people say that variables should be declared as close to their usage as possible. I don't understand this.

For example, this policy would suggest I should do this:

foreach (var item in veryLongList) {
  int whereShouldIBeDeclared = item.Id;
  //...
}

But surely this means the overheads of creating a new int are incurred on every iteration. Wouldn't it be better to use:

int whereShouldIBeDeclared;
foreach (var item in veryLongList) {
  whereShouldIBeDeclared = item.Id;
  //...
}

Please could somebody explain?

share|improve this question
3  
It would be a pretty damn poor language that treated those two cases differently. –  Paul Tomblin Oct 9 '11 at 14:14
5  
You a starting from a false premise. Please see my answer to this question: stackoverflow.com/questions/6919655/… –  CesarGon Oct 9 '11 at 14:23
8  
If you think like that, you're not fit for optimizing or even considering performance impacts in general. Language implementations are smart, and if you think they aren't, prove it with hard data obtained through unbiased, realistic benchmarks. –  delnan Oct 9 '11 at 14:41
4  
If the two code examples have a significant semantic difference, then they do different things. You should use the one that does what you want to do. The rule about where you declare variables only applies to cases where it makes no semantic difference. –  David Schwartz Oct 9 '11 at 15:27
4  
Consider the opposite end of the scale - everything being a global variable. Surely 'declared near usage' is the better end of this spectrum? –  JBRWilkinson Oct 10 '11 at 11:52
show 2 more comments

6 Answers 6

up vote 19 down vote accepted

This is one style rule among many, and it isn't necessarily the most important rule of all the possible rules you could consider. Your example, since it includes an int, isn't super compelling, but you could certainly have an expensive-to-construct object inside that loop, and perhaps a good argument for constructing the object outside the loop. However, that doesn't make it a good argument against this rule since first, there are tons of other places it could apply that don't involve constructing expensive objects in a loop, and second, a good optimizer (and you've tagged C#, so you have a good optimizer) can hoist the initialization out of the loop.

The real reason for this rule is also the reason you don't see why it's a rule. People used to write functions that were hundreds, even thousands of lines long and they used to write them in plain text editors (think Notepad) without the kind of support Visual Studio provided. In that environment, declaring a variable hundreds of lines away from where it was used meant that the person reading

if (flag) limit += factor;

didn't have a lot of clues about what flag, limit and factor were. Naming conventions like Hungarian notation were adopted to help with this, and so were rules like declaring things close to where they are used. Of course, these days, it's all about refactoring, and functions are generally less than a page long, making it hard to get very much distance between where things are declared and where they are used. You're operating in a range of 0-20 and quibbling that maybe 7 is ok in this particular instance, while the guy who made the rule would have LOVED to get 7 lines away and was trying to talk someone down from 700. And on top of that, in Visual Studio, you can mouse over anything and see its type, is it a member variable, and so on. That means the need to see the line declaring it is lessened.

It's still a reasonably good rule, one that's actually quite hard to break these days, and one that no-one ever advocated as a reason to write slow code. Be sensible, above all.

share|improve this answer
    
Thanks for your answer. But surely regardless of the data type, a new instance is created on every iteration whichever way I do it? It's just that in the second case we don't ask for a new memory reference each time. Or have I missed the point? And are you saying that the C# optimizer will automatically improve my code when it compiles anyway? I didn't know that! –  James Oct 9 '11 at 14:12
2  
The overhead of creating an int is tiny. If you were constructing something complicated, the overhead would be a bigger deal. –  Kate Gregory Oct 9 '11 at 14:17
10  
It's not only a question of being able to see its type and such. It's also a question of lifetime. If the variable "wibble" is declared 30 lines before it's first used, there are 30 lines in which a mistaken use of "wibble" can result in a bug. If it's declared immediately before it's used, using "wibble" in those 30 previous lines won't result in a bug. It'll cause a compiler error instead. –  Mike Sherrill 'Cat Recall' Oct 9 '11 at 17:57
    
In this case, a new instance is not created every loop. A single top-level variable is created and used for every iteration (look at the IL). But that's an implementation detail. –  thecoop Oct 10 '11 at 12:14
    
" in Visual Studio, you can mouse over anything and see" etc. There is also Navigate to definition, which has the shortcut F12 which is indispensable. –  StuperUser Oct 10 '11 at 12:18
show 1 more comment

Defining the variable inside the loop makes it visibility local to that loop only. This has at least 3 advantages for the reader:

  1. The variable definition and any related comments are easy to find
  2. The reader knows that this variable is never used else where (no dependency to expect)
  3. When the code is written or edited, there is no chance that you could use the same variable name outside the loop to refer to that variable otherwise, you could get in error.

As for the efficiency bit, the compiler is smart to generate the definition outside of the loop in the optimized code generated. The variable will not be created every loop iteration.

share|improve this answer
add comment

People say as close to their usage as possible , They are not saying you should have to do that all the time,because they are some cases declaring variables in least scope will cause some overhead .The main reasons of that statement are Readability and giving variables the smallest scope you can .

share|improve this answer
add comment

Although it helps with readability, readability isn't the primary consideration in this case, and modern IDEs don't obviate the need for this rule.

The primary concern is uninitialized variables. If you declare a variable too far away from its initialization, it opens you up to all kinds of potential problems. You might find yourself accidentally working with whatever happened to be there in RAM before, or the result from a calculation higher in the function, or a dummy initialization (like 0) that someone put in just to keep the compiler from complaining. People will insert code in between your declaration and usage without being aware of your implicit preconditions for that variable. In the worst cases, that usage will just happen to work in your tests but fail in the field.

Declaring your variables in as small a scope as possible, and initializing them to a proper value right at the point of declaration will avoid a great many maintenance headaches. The fact that it compels improved readability is just a nice side effect.

share|improve this answer
add comment

It is not a "must". It's just an opinion, I way to do something. For example, I like to declare all the vars in the first lines of the method so I can comment what I'll do with that vars (of course unless they are counters). Other people, as you heard, like to place them as close to their usage as possible (as in the second example you wrote). Anyway, the first example you provide is surely an "error" (in the sense that it will cause an overhead as you understand).

You have simply to choose your way and follow it.

share|improve this answer
1  
It's not just an opinion, is it? Hasn't software engineering research documented the relationship between live time and number of bugs since at least the 1980s? –  Mike Sherrill 'Cat Recall' Oct 9 '11 at 18:00
add comment

Your two examples are functionally different code, they're not interchangeable. (Your stripped down examples leave it a distinction without a difference, but in non-trivial code it does make a difference). The rule you site is always subordinate to scoping considerations, as indicated by "...as possible".

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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