Avatar ·

لماذا يتم التقاط متغير حلقة 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` متغير الحل