Khi sử dụng biểu thức lambda hoặc phương thức ẩn danh trong C #, chúng ta phải cảnh giác với quyền truy cập vào cạm bẫy đóng cửa được sửa đổi . Ví dụ:
foreach (var s in strings)
{
query = query.Where(i => i.Prop == s); // access to modified closure
...
}
Do đóng cửa được sửa đổi, đoạn mã trên sẽ khiến tất cả các Where
mệnh đề trên truy vấn được dựa trên giá trị cuối cùng của s
.
Như đã giải thích ở đây , điều này xảy ra vì s
biến được khai báo trong foreach
vòng lặp ở trên được dịch như thế này trong trình biên dịch:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
thay vì như thế này:
while (enumerator.MoveNext())
{
string s;
s = enumerator.Current;
...
}
Như đã chỉ ra ở đây , không có lợi thế về hiệu suất khi khai báo một biến ngoài vòng lặp và trong các trường hợp thông thường, lý do duy nhất tôi có thể nghĩ đến để làm điều này là nếu bạn dự định sử dụng biến ngoài phạm vi của vòng lặp:
string s;
while (enumerator.MoveNext())
{
s = enumerator.Current;
...
}
var finalString = s;
Tuy nhiên, các biến được xác định trong một foreach
vòng lặp không thể được sử dụng bên ngoài vòng lặp:
foreach(string s in strings)
{
}
var finalString = s; // won't work: you're outside the scope.
Vì vậy, trình biên dịch khai báo biến theo cách khiến nó rất dễ bị lỗi thường khó tìm và gỡ lỗi, trong khi không tạo ra lợi ích rõ ràng.
Có điều gì bạn có thể làm với foreach
các vòng lặp theo cách này mà bạn không thể làm được nếu chúng được biên dịch với biến có phạm vi bên trong không, hay đây chỉ là một lựa chọn tùy ý được thực hiện trước khi các phương thức ẩn danh và biểu thức lambda có sẵn hoặc phổ biến Kể từ đó đã được sửa đổi?
foreach
nhưng các biểu thức lamda dẫn đến mã tương tự như được hiển thị bởi OP ...
String s; foreach (s in strings) { ... }
vậy?