لماذا يتم التقاط متغير حلقة foreach بشكل غير صحيح في C#؟
مرحباً بالجميع! بدأت مؤخراً في تعلم C# وواجهت سلوكاً غريباً جداً عند استخدام تعبيرات lambda داخل حلقة `foreach`.
لدي كود بسيط حيث أقوم بإنشاء قائمة من الإجراءات التي يجب أن تطبع الأرقام من 0 إلى 4:
```csharp
var actions = new List();
for (int i = 0; i < 5; i++)
{
actions.Add(() => Console.WriteLine(i));
}
foreach (var action in actions)
{
action();
}
```
هذا الكود يطبع: 5, 5, 5, 5, 5. أفهم أن هذا بسبب أن المتغير `i` يتم التقاطه بواسطة reference، وعند لحظة استدعاء lambda يكون قد أصبح 5. هذا منطقي.
لكن عندما أفعل نفس الشيء مع `foreach`:
```csharp
var actions = new List();
foreach (var i in Enumerable.Range(0, 5))
{
actions.Add(() => Console.WriteLine(i));
}
foreach (var action in actions)
{
action();
}
```
في الإصدارات القديمة من C# (قبل 5.0) كان هذا الكود يطبع أيضاً 5, 5, 5, 5, 5. لكن بدءاً من C# 5.0 أصبح يطبع 0, 1, 2, 3, 4.
لماذا يحدث هذا؟ ففي `foreach` متغير الحل