Code blocks are often referred to as scopes, but the two terms are not exactly interchangeable. The scope of a named thing is the region of source code in which it is legal to refer to the thing by its unqualified name. The scope of a local variable, for example, is exactly the text of the code block that encloses it, which explains why it is common to refer to code blocks as scopes.
Scopes are often confused with declaration spaces. A declaration space is a logical container of named things in which two things may not have the same name. A code block defines not only a scope but also a local variable declaration space. It is illegal for two local variable declarations with the same name to appear in the same declaration space. Similarly, it is not possible to declare two methods with the signature of Main() within the same class. (This rule is relaxed somewhat for methods: Two methods may have the same name in a declaration space provided that they have different signatures. The signature of a method includes its name and the number and types of its parameters.) Within a block, a local variable can be mentioned by name and must be the unique thing that is declared with that name in the block. Outside the declaring block, there is no way to refer to a local variable by its name; the local variable is said to be “out of scope” outside the block.
In summary, C# uses a scope to determine what thing a name refers to; a declaration space determines when two things declared with the same name conflict with each other. In Listing 4.28 (with Output 4.15), declaring the local variable message inside the block statement embedded in the if statement restricts its scope to the block statement only; the local variable is out of scope when its name is used later in the method. To avoid an error, you must declare the variable outside the block.
The declaration space in which a local variable’s name must be unique encompasses all the child code blocks textually enclosed within the block that originally declared the local. The C# compiler prevents the name of a local variable declared immediately within a method code block (or as a parameter) from being reused within a child code block. In Listing 4.28, because args and playerCount are declared within the method code block, they cannot be declared again anywhere within the method.
The name message refers to this local variable throughout the scope of the local variable—that is, the block immediately enclosing the declaration. Similarly, playerCount refers to the same variable throughout the block containing the declaration, including within both of the child blocks that are the consequence and the alternative of the if statement.
In C++, a local variable declared in a block is in scope from the point of the declaration statement through the end of the block. Thus, an attempt to refer to the local variable before its declaration will fail to find the local variable because that variable is not in scope. If there is another thing with that name “in scope,” the C++ language will resolve the name to that thing, which might not be what you intended. In C#, the rule is subtly different: A local variable is in scope throughout the entire block in which it is declared, but it is illegal to refer to the local variable before its declaration. That is, an attempt to find the local variable will succeed, and the usage will then be treated as an error. This is just one of C#’s many rules intended to prevent errors common in C++ programs.