Why C# Reuses the Variable in foreach? A Beginner's Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: The Puzzle That Bothers Beginners

\n\n

Imagine this: you write a simple foreach loop in C#, save a lambda expression or start an asynchronous task inside the loop, and suddenly get a completely unexpected result. All the variables you thought you carefully "captured" end up referencing the last element of the collection. Sound familiar?

\n\n

On Stack Overflow, the question "Is there a reason for C#'s reuse of the variable in a foreach?" has gathered thousands of views and numerous comments. This isn't just an academic curiosity — it's a practical trap that even experienced developers fall into. In this article, we'll break down why C# does this, how it has changed across language versions, and most importantly, how to avoid related bugs.

\n\n

We'll explain in simple terms, with code examples, so even a C# beginner can understand the core issue. Let's go!

\n\n

The Core Problem: What Does "Variable Reuse" Mean?

\n\n

In the classic foreach loop in C# (before version 5.0), the iteration variable was declared once for the entire loop, rather than being created anew for each iteration. This means that if you capture this variable in a closure (e.g., in a lambda expression or anonymous method), all closures will reference the same variable.

\n\n

Let's look at the classic example of the problem:

\n\n
var actions = new List<Action>();\nvar numbers = new List<int> { 1, 2, 3, 4, 5 };\n\nforeach (var number in numbers)\n{\n    actions.Add(() => Console.WriteLine(number));\n}\n\n// Execute all actions\nforeach (var action in actions)\n{\n    action();\n}\n
\n\n

Question: What does this code output? Intuitively, you'd expect 1, 2, 3, 4, 5. But in reality (before C# 5), it would output 5, 5, 5, 5, 5.

\n\n

Why? Because the variable number exists as a single instance throughout the entire loop. When the loop finishes, its value equals the last element (5). All lambdas captured a reference to this variable, not its value at the time of creation.

\n\n

Analogy for Understanding

\n\n

Imagine you have a box (the variable), and you put different items (values) into it one by one. You give your friends (the lambdas) not the items themselves, but the key to the box. When your friends come to pick up their items, they open the box, and inside is the last item you placed there. That's how the old foreach works.

\n\n

Historical Context: Why Was It Done This Way?

\n\n

Many beginners ask: "This is a bug! Why do it this way?" In fact, it was a deliberate decision by the C# developers, based on performance and compiler simplicity.

\n\n
    \n
  • Performance: Creating a new variable on each iteration requires additional memory allocation. For most simple loops, this isn't critical, but in high-load systems, every micro-optimization matters.
  • \n
  • Consistency with for: In a for loop, the variable is also declared once. Developers wanted to maintain consistency.
  • \n
  • Compiler simplicity: The old approach was easier to implement in the compiler. But the cost was non-obvious behavior for programmers.
  • \n
\n\n

However, the community quickly discovered this "feature" and started filing bug reports. The Stack Overflow question "Is there a reason for C#'s reuse of the variable in a foreach?" became one of the most popular. Microsoft listened, and in C# 5.0 (2012), the behavior was changed.

\n\n

What Changed in C# 5.0?

\n\n

Starting with C# 5.0, the compiler creates a new variable for each iteration of the foreach loop. Now, the example above will work intuitively correctly and output 1, 2, 3, 4, 5.

\n\n
// This                

Blogs

Book Recommendations