เมื่อใช้แลมบ์ดานิพจน์หรือวิธีที่ไม่ระบุตัวตนใน C # เราต้องระวังการเข้าถึงหลุมพรางปิดที่มีการแก้ไข ตัวอย่างเช่น:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
เนื่องจากการปิดการปรับเปลี่ยนรหัสดังกล่าวข้างต้นจะทำให้ทั้งหมดของคำสั่งในการค้นหาให้เป็นไปตามค่าสุดท้ายของWhere
s
ดังที่อธิบายไว้ที่นี่สิ่งนี้เกิดขึ้นเพราะs
ตัวแปรที่ประกาศในforeach
ลูปด้านบนถูกแปลเช่นนี้ในคอมไพเลอร์:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
แทนที่จะเป็นเช่นนี้:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
ดังที่กล่าวไว้ที่นี่ไม่มีข้อได้เปรียบด้านประสิทธิภาพในการประกาศตัวแปรภายนอกลูปและภายใต้สถานการณ์ปกติเหตุผลเดียวที่ฉันคิดได้สำหรับการทำเช่นนี้คือถ้าคุณวางแผนที่จะใช้ตัวแปรนอกขอบเขตของลูป:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
อย่างไรก็ตามตัวแปรที่กำหนดในforeach
ลูปไม่สามารถใช้ภายนอกลูปได้:
foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.
ดังนั้นคอมไพเลอร์จึงประกาศตัวแปรในลักษณะที่ทำให้เกิดข้อผิดพลาดสูงซึ่งมักจะยากที่จะค้นหาและตรวจแก้จุดบกพร่องในขณะที่ไม่มีประโยชน์ที่รับรู้ได้
มีบางสิ่งที่คุณสามารถทำกับforeach
ลูปได้ด้วยวิธีนี้ถ้าคุณไม่ได้คอมไพล์ด้วยตัวแปรภายในหรือนี่เป็นเพียงตัวเลือกโดยพลการที่ทำขึ้นก่อนวิธีที่ไม่ระบุชื่อและการแสดงออกแลมบ์ดานั้นมีอยู่หรือทั่วไป ไม่ได้รับการแก้ไขตั้งแต่นั้นมา?
foreach
แต่เกี่ยวกับนิพจน์ Lamda ผลในรหัสที่คล้ายกันที่แสดงโดยสหกรณ์ ...
String s; foreach (s in strings) { ... }
?