#1,105 – Re-Declaring a Class-Level Variable within a Method

You can re-declare a class-level variable within a method, that is–declare a local variable having the same name as a class-level variable.  Within the scope of the method, the local variable will hide the class-level variable.

    public class MyClass
    {
        public int x = 10;

        public void MethodA()
        {
            double x = 4.2;
            Console.WriteLine(x);
        }
    }

1105-001
You cannot, however, reference a class-level variable before declaring the local variable, since this is interpreted as referencing the local variable before it is defined.

        public void MethodA()
        {
            // ERROR: Can't use local variable before it's declared
            Console.WriteLine(x);

            double x = 4.2;
            Console.WriteLine(x);
        }

You also can’t reference the class-level variable in an outer scope.

        public void MethodA()
        {
            Console.WriteLine(x);

            if (DateTime.Now.DayOfWeek == DayOfWeek.Tuesday)
            {
                // ERROR: Can't declare local variable within this scope
                double x = 4.2;
                Console.WriteLine(x);
            }
        }
Advertisement

#1,104 – Can’t Re-Declare a Variable within a Nested Block

A declaration space is a region of code within which you can’t declare two entities having the same name.  

Defining a class creates a new declaration space, i.e. you can declare variables at the class level.

Defining a method creates a new declaration space, known as a local variable declaration space.  A block of code within that method creates a nested local variable declaration space.

It’s of course an error to declare two variables of the same name within a local variable declaration space.  It’s also an error to re-declare a variable of the same name in a nested local variable declaration space.

        public void MethodA()
        {
            int y = 1;
            string y = "oops";  // ERROR

            int x = 12;
            Console.WriteLine(12);

            if (DateTime.Now.DayOfWeek == DayOfWeek.Thursday)
            {
                // ERROR: Can't re-declare x within nested local variable declaration space
                double x = 4.2;
                Console.WriteLine(x);
            }
        }

#1,103 – A Block Defines Both Scope and Declaration Space

  • Scope is the region of code in which you can refer to a named entity using its unqualified name.
  • Declaration space is a region of code within which you can’t declare two entities having the same name

A block of statements defines both a new scope and a new declaration space.

In the code below, the variable msg is declared within the block of statements following the if statement.

    public class MyClass
    {
        public void AMethod()
        {
            if (DateTime.Now.DayOfWeek == DayOfWeek.Thursday)
            {
                // Can define variables within this block
                string msg = "Hi";
                Console.WriteLine("{0}, it's Thursday. ", msg);
            }

            // ERROR: The name 'msg' does not exist in the current context
            Console.WriteLine(msg);
        }
    }

The block defines a new scope–the variable msg can be referred to by name anywhere within the block (after the declaration).  This block also defines a declaration space–you can only declare one variable named msg within this block.

#1,102 – Scope vs. Declaration Space

The terms scope and declaration space are similar, but slightly different.

  • Scope is the region of code in which you can refer to a named entity using its unqualified name.
  • Declaration space is a region of code within which you can’t declare two entities having the same name

For example:

    public class MyClass
    {
        int count1 = 1;
        int count2 = 2;

        public void AMethod()
        {
            int count2 = 22;

            Console.WriteLine(count1 + ", " + count2);
        }
    }

Then:

  • The class-level declarations of count1 and count2 are in the same scope and in the same declaration space
  • The body of function AMethod()
    • is included in the scope in which class-level fields are defined, i.e. you can reference them using their unqualified name.
    • defines a new declaration space, i.e. we can define a new variable of the same name as the class-level fields
    • defines a new scope, in which we can define variables, nested within outer scope

1102-001

#718 – Scope

In C#, every name has a scope.  The scope of a name is the region of code in which you can refer to that name using just the unqualified name.

Here are some examples:

  • The scope of a type defined within a namespace is all code also defined in that namespace
  • The scope of a member declared in a class is the body of that class
  • The scope of a parameter declared in a method is the body of that method
  • The scope of a local variable is the method in which it is defined
  • The scope of a local variable defined within a block is the body of that block

#710 – Variables Declared in a Block Aren’t Visible Outside of the Block

If you declare a variable within a code block, that variable is usable only within the scope of that block.  It is not visible and can’t be referenced outside of the block.

        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                string promise = "I will not pull my sister's pigtails";
                Console.WriteLine(promise);
            }

            // Compile-time Error: The name 'promise' does not exist in the current context
            Console.WriteLine(promise);
        }

#502 – #define and #undef Scope

When you include a #define or #undef preprocessor directive in a file, the scope in which that conditional symbol is defined (or not defined) is limited to that single file.

For example, suppose that we define the symbol QUIET within a file that creates an instance of a Dog and then calls the Bark method of the Dog object.

// Code from Program.cs
#define QUIET

using System;
using DogLibrary;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Dog d1 = new Dog("Kirby", 12);
            d1.Bark();
        }
    }
}

Let’s also suppose that the Dog.Bark method, which exists in a separate file, compiles differently depending on whether the symbol QUIET is defined.

// Code from Dog.cs
        public void Bark()
        {
#if QUIET
            Console.WriteLine("Arf");
#else
            Console.WriteLine("WOOOOOF!");
#endif
        }

Because QUIET is defined in Program.cs but not in Dog.cs, the Bark method will use the second (not quiet) line.