Rumah >pembangunan bahagian belakang >C++ >Mengapakah semua ungkapan lambda dalam gelung foreach menangkap pembolehubah yang sama dan bukannya nilai individunya?
Pembolehubah yang Ditangkap dalam Ungkapan Lambda: Menyahmistifikasi Misteri "Foreach Loop Variable"
Pertimbangkan kod yang membingungkan di bawah, yang bertujuan untuk membuat senarai kaedah yang menyambut pelbagai jenis data:
public class MyClass { public delegate string PrintHelloType(string greeting); public void Execute() { Type[] types = new Type[]{typeof(string), typeof(float), typeof(int)}; List<PrintHelloType> helloMethods = new List<PrintHelloType>(); foreach (var type in types) { var sayHello = new PrintHelloType(greeting => SayGreetingToType(type, greeting)); helloMethods.Add(sayHello); } foreach (var helloMethod in helloMethods) { Console.WriteLine(helloMethod("Hi")); } } public string SayGreetingToType(Type type, string greetingText) { return greetingText + " " + type.Name; } }
Walau bagaimanapun, apabila anda menjalankan kod ini, anda menemui hasil yang tidak dijangka: ia mencetak "Hi Int32" tiga kali, bukannya "Hi String" yang dimaksudkan, "Hai Bujang", "Hi Int32". Apa yang berlaku di sini?
Kehalusan Penutupan dan Pembolehubah Ditangkap
Kunci untuk memahami tingkah laku ini terletak pada konsep penutupan dan pembolehubah yang ditangkap. Apabila ungkapan lambda dicipta, ia menangkap pembolehubah daripada skop sekelilingnya. Dalam kes ini, ungkapan lambda menangkap pembolehubah jenis daripada gelung foreach.
Pembolehubah Gelung Ditangkap: Satu Perangkap
Yang penting, pembolehubah yang ditangkap bukanlah nilai jenis, tetapi pembolehubah itu sendiri. Apabila gelung berlangsung, pembolehubah jenis berubah, manakala ungkapan lambda masih merujuk kepada pembolehubah yang ditangkap yang sama.
Membetulkan Isu
Untuk mencapai kelakuan yang dimaksudkan, ia adalah perlu untuk mencipta pembolehubah baharu dalam gelung untuk menangkap nilai yang dimaksudkan. Begini cara untuk mengubah suai kod:
foreach (var type in types) { var newType = type; var sayHello = new PrintHelloType(greeting => SayGreetingToType(newType, greeting)); helloMethods.Add(sayHello); }
Dengan menangkap newType dan bukannya jenis, ungkapan lambda kini mempunyai rujukan tetap kepada nilai yang dimaksudkan dan output yang dijangkakan diperoleh.
Kesimpulan
Memahami selok-belok penutupan dan pembolehubah yang ditangkap adalah penting apabila bekerja dengan ungkapan lambda. Dengan mengambil kira mekanik ini, anda boleh mengelakkan tingkah laku yang tidak dijangka dan memastikan kod anda berfungsi seperti yang dimaksudkan.
Atas ialah kandungan terperinci Mengapakah semua ungkapan lambda dalam gelung foreach menangkap pembolehubah yang sama dan bukannya nilai individunya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!