Cập nhật 17/07/2012: Rõ ràng là từ C # 5.0, hành vi foreach
được mô tả dưới đây đã được thay đổi và " việc sử dụng foreach
biến lặp trong biểu thức lambda lồng nhau không còn tạo ra kết quả bất ngờ. " Câu trả lời này không áp dụng cho C # 5.0 .
@ John Skeet và tất cả những người thích từ khóa foreach.
Vấn đề với "foreach" trong C # trước 5.0 , là nó không phù hợp với cách thức "hiểu" tương đương trong các ngôn ngữ khác và với cách tôi mong đợi nó hoạt động (ý kiến cá nhân chỉ nêu ở đây vì những người khác đã đề cập ở đây ý kiến về khả năng đọc). Xem tất cả các câu hỏi liên quan đến " Truy cập vào đóng cửa được sửa đổi " cũng như " Đóng trên biến vòng lặp được coi là có hại ". Điều này chỉ "có hại" vì cách "foreach" được thực hiện trong C #.
Lấy các ví dụ sau bằng cách sử dụng phương thức mở rộng tương đương về chức năng với câu trả lời của @Fredrik Kalseth.
public static class Enumerables
{
public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action)
{
foreach (T item in @this)
{
action(item);
}
}
}
Lời xin lỗi cho ví dụ quá mức. Tôi chỉ sử dụng Observable vì nó không hoàn toàn xa để làm một cái gì đó như thế này. Rõ ràng có nhiều cách tốt hơn để tạo ra điều này có thể quan sát được, tôi chỉ đang cố gắng chứng minh một điểm. Thông thường, mã được đăng ký để có thể quan sát được thực thi không đồng bộ và có khả năng trong một luồng khác. Nếu sử dụng "foreach", điều này có thể tạo ra kết quả rất kỳ lạ và có khả năng không xác định.
Thử nghiệm sau bằng cách sử dụng phương thức mở rộng "ForEach":
[Test]
public void ForEachExtensionWin()
{
//Yes, I know there is an Observable.Range.
var values = Enumerable.Range(0, 10);
var observable = Observable.Create<Func<int>>(source =>
{
values.ForEach(value =>
source.OnNext(() => value));
source.OnCompleted();
return () => { };
});
//Simulate subscribing and evaluating Funcs
var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();
//Win
Assert.That(evaluatedObservable,
Is.EquivalentTo(values.ToList()));
}
Lỗi sau đây với lỗi:
Dự kiến: tương đương với <0, 1, 2, 3, 4, 5, 6, 7, 8, 9> Nhưng là: <9, 9, 9, 9, 9, 9, 9, 9, 9, 9>
[Test]
public void ForEachKeywordFail()
{
//Yes, I know there is an Observable.Range.
var values = Enumerable.Range(0, 10);
var observable = Observable.Create<Func<int>>(source =>
{
foreach (var value in values)
{
//If you have resharper, notice the warning
source.OnNext(() => value);
}
source.OnCompleted();
return () => { };
});
//Simulate subscribing and evaluating Funcs
var evaluatedObservable = observable.ToEnumerable().Select(func => func()).ToList();
//Fail
Assert.That(evaluatedObservable,
Is.EquivalentTo(values.ToList()));
}
ForEach()
.