"Convert to LINQ" converts variable that is modified in the loop to immutable iterator variable
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
**Version Used**: VS 18.0.0 [11111.19]
**Steps to Reproduce**:
Take this piece of code, which has two foreach loops. If the inner loop was executed (i.e. M2 yielded any elements), a flag is set to continue with the next iteration of the outer loop and skip the alternative execution path (M4).
Open the lightbulb menu on the outer `foreach` token and select "Convert to LINQ".
```csharp
class C
{
public void M(IEnumerable strings)
{
foreach (var v1 in strings)
{
bool b = false;
foreach (var v in M2())
{
M3(v);
b = true;
}
if (b)
{
continue;
}
M4();
}
}
IEnumerable M2()
{
yield break;
}
void M3(object v) { }
void M4() { }
}
```
**Expected Behavior**:
Either the refactoring produces legal code, or it is not offered here.
**Actual Behavior**:
`b` is converted into a foreach iterator variable, which is immutable, leading to compiler error `CS1656: Cannot assign to 'b' because it is a 'foreach iteration variable'` on the `b = true;` statement.
```csharp
foreach (var b in from v1 in strings
let b = false
select b)
{
foreach (var v in M2())
{
M3(v);
b = true;
}
if (b)
{
continue;
}
M4();
}
```
Contributor guide
Research direction
Start with the Roslyn "Convert to LINQ" refactoring entry point and reproduce the issue using the C# snippet in the report. Check the generated query for assignments to variables captured as foreach iteration variables; done means the refactoring either produces compilable code or is not offered for this case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100