Поделиться через


What is the defining characteristic of a local variable?

If you ask a dozen C# developers what a "local variable" is, you might get a dozen different answers. A common answer is of course that a local is "a storage location on the stack". But that is describing a local in terms of its implementation details; there is nothing in the C# language that requires that locals be stored on a data structure called "the stack", or that there be one stack per thread. (And of course, locals are often stored in registers, and registers are not the stack.)

A less implementation-detail-laden answer might be that a local variable is a variable whose storage location is "allocated from the temporary store". That is, a local variable is a variable whose lifetime is known to be short; the local's lifetime ends when control leaves the code associated with the local's declaration space.

That too, however, is a lie. The C# specification is surprisingly vague about the lifetime of an "ordinary" local variable, noting that its lifetime is only kinda-sorta that length. The jitter's optimizer is permitted broad latitude in its determination of local lifetime; a local can be cleaned up early or late. The specification also notes that the lifetimes of some local variables are necessarily extended beyond the point where control leaves the method body containing the local declaration. Locals declared in an iterator block, for instance, live on even after control has left the iterator block; they might die only when the iterator is itself collected. Locals that are closed-over outer variables of a lambda are the same way; they live at least as long as the delegate that closes over them. And in the upcoming version of C#, locals declared in async blocks will also have extended lifetimes; when the async method returns to its caller upon encountering an "await", the locals live on and are still there when the method resumes. (And since it might not resume on the same thread, in some bizarre situations, the locals had better not be stored on the stack!)

So if locals are not "variables on the stack" and locals are not "short lifetime variables" then what are locals?

The answer is of course staring you in the face. The defining characteristic of a local is that it can only be accessed by name in the block which declares it; it is local to a block. What makes a local truly unique is that it can only be a private implementation detail of a method body. The name of that local is never of any use to code lexically outside of the method body.

Comments

  • Anonymous
    January 16, 2012
    That was my thinking too, although you've phrased it much better.

  • Anonymous
    January 16, 2012
    It's a shame that this needs to be clarified, but it's a reflection of how most people think, not just programmers: they define things by their side effects rather than by what they are.

  • Anonymous
    January 16, 2012
    I tried to define a local variable for myself before reading this article. My definition was reasonably close to yours. This is probably partially due to having read your post on the stack as an implementation detail previously. Having a clear understanding of these things can certainly help avoid bugs due to misconceptions.

  • Anonymous
    January 16, 2012
    The comment has been removed

  • Anonymous
    January 16, 2012
    >> The defining characteristic of a local is that it can only be accessed by name in the block which declares it This merits a question about ref variables ... since a ref/out variable is an alias for a named local variable why is that not considered "referenced by name"? While it's true that the ref/out parameter to a method may have a different name from the variable that is passed to the method, it still seems like an exception to the general characteristic that the variable can only be referenced in the block which declares it; no?

  • Anonymous
    January 16, 2012
    The comment has been removed

  • Anonymous
    January 16, 2012
    Method parameters cannot be considered the same as local variables using Eric's definition "What makes a local truly unique is that it can only be a private implementation detail of a method body". As C# now allows the parameter's name to be known by the calling method (for named arguments) this would be untrue.

  • Anonymous
    January 16, 2012
    The comment has been removed

  • Anonymous
    January 16, 2012
    To me this definition does not look complete. I'm missing the fact that with each "invocation" a private instance of a local variable is created, in contrast of being a singleton. Concurrent "invocations" (for instance by means of threads or recursion) have their own private instances which do not interfere. "Invocation" is a little bit fuzzy as there are iterator blocks and other funny constructs.

  • Anonymous
    January 17, 2012
    @Steffen:  I like Eric's definition because it specifically does not conflate these two concepts.  It just so happens that in C# a local variable nearly always has automatic storage(), but that's not a requirement in general.  For example, both C and C++ support locat variables with static storage. () Think about ref and out parameters

  • Anonymous
    January 18, 2012
    I am with Bill on this. What about lambdas and anonymous functions closing over local variables? In this case, if you are really creative you can reflect over them through generated class.