LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 1910 min read

Scope

Understand variable scope, local variables, and block scoping in C#.

What is Scope?

Scope determines where in your code a variable is visible and usable. In C#, a variable exists only within the block of code (marked by curly braces { }) where it was declared, and everything nested inside that block — but nowhere outside it.

Block Scope

if (true)
{
int x = 10;
Console.WriteLine(x); // fine, x is in scope here
}
// Console.WriteLine(x); // Error: x doesn't exist here — it went out of scope

A variable declared in an outer block IS visible to nested inner blocks — scope only restricts visibility going outward, never inward.

int outer = 100;
if (true)
{
Console.WriteLine(outer); // fine — inner blocks can see outer variables
int inner = 5;
}
// Console.WriteLine(inner); // Error — inner doesn't exist out here

Method Scope

Variables declared inside a method are local to that method and cease to exist entirely once the method returns — each call gets a completely fresh set of local variables, with no memory of any previous call's values.

static void Counter()
{
int count = 0; // reset to 0 on every single call
count++;
Console.WriteLine(count);
}
Counter(); // 1
Counter(); // 1 again — NOT 2, since count is freshly created each call
Fun Fact

If you genuinely need a value to persist across multiple calls to the same method, that's exactly what a static field (covered in the Static Members lesson) or a class instance field is for — local variables, by design, can never survive between calls.

Loop Variable Scope

A for loop's counter variable is scoped to the loop itself — it doesn't exist before or after the loop, which is exactly why you can reuse the same variable name (like i) in multiple separate loops within the same method without any conflict.

for (int i = 0; i < 3; i++) { Console.WriteLine(i); }
for (int i = 0; i < 5; i++) { Console.WriteLine(i); } // a totally separate 'i' — no conflict

Why C# Disallows Shadowing

Some languages (including JavaScript) allow "shadowing" — declaring a new variable with the same name as one already in scope in an enclosing block, silently hiding the outer one. C# deliberately disallows this at compile time.

int value = 10;
if (true)
{
int value = 20; // ❌ Compile error — "value" already exists in an enclosing scope
}
Unlike Some Languages, C# Disallows Shadowing

C# will not let you declare a variable with the same name as one already in scope in an enclosing block — this catches a real, common class of bugs (accidentally referencing the wrong variable) directly at compile time, rather than letting it silently succeed and cause confusion later.

Common Beginner Mistakes

Trying to use a variable outside the block it was declared in

A variable declared inside an if block's braces simply doesn't exist once you're past the closing brace — declare it in an outer scope first if you need it afterward.

Expecting a local variable to remember its value between method calls

Every call to a method creates entirely fresh local variables — use a static field or an instance field on a class if state genuinely needs to persist across calls.

FAQs

No — fields (covered in the Classes & Objects lesson) belong to the whole object for its entire lifetime, and follow access modifier rules (public, private, etc.) instead of block scope.

No — a variable declared in a for loop's initializer (like int i) is scoped to the loop itself; declare it before the loop if you need its final value afterward.

It reflects a difference in language design philosophy — C# generally favors catching potentially confusing situations at compile time over allowing flexible-but-riskier patterns.

Key Takeaways

  • A variable only exists within the block (and any nested blocks) where it's declared — never outside it.
  • Local variables reset completely on every method call, with no memory of previous calls.
  • A for loop's counter is scoped to the loop, so the same variable name is reusable across separate loops.
  • C# disallows shadowing a variable name from an enclosing scope, catching a common bug at compile time.

Summary

Understanding scope precisely — where a variable lives and dies — prevents confusing "variable doesn't exist" errors and clarifies exactly when state does or doesn't persist. Next, you'll learn exception handling, for gracefully dealing with errors that occur while your program runs.

Next Lesson →

Exception Handling