2010-10-23 46 views
13

Tại sao vòng lặp foreach chỉ đọc? Ý tôi là bạn có thể tìm nạp dữ liệu nhưng không thể tăng ++ hoặc giảm--. Bất kỳ lý do đằng sau nó? Có Tôi là một người mới bắt đầu :)Tại sao vòng lặp foreach chỉ đọc trong C#

Exmaple:

int[] myArray={1,2,3}; 
foreach (int num in myArray) 
{ 
    num+=1; 
} 
+1

Ý anh là gì của vòng lặp while được read-only? Vòng lặp while là một cấu trúc; nó không chỉ đọc và đọc. Có thể bạn có thể đăng một số mã và/hoặc làm rõ câu hỏi của bạn, xin vui lòng? Cảm ơn. – CesarGon

+1

Tôi nghĩ rằng anh ta đang nói về biến lặp, như trong foreach (Item theItem trong theItemList) ... theItem không thể được gán cho. –

+0

Bây giờ anh ta đã làm sáng tỏ câu hỏi: anh ta đang nói về việc rao giảng thay vì trong thời gian đó. – CesarGon

Trả lời

9

Đó là bởi vì foreach là có nghĩa là để lặp qua một thùng chứa, đảm bảo mỗi mục được truy cập một cách chính xác một lần, mà không thay đổi container, để tránh khó chịu tác dụng phụ.

Xem: foreach in MSDN

Nếu bạn có nghĩa là lý do tại sao sẽ thay đổi một yếu tố giống như một số nguyên không ảnh hưởng đến một container của số nguyên, cũng là vì các biến lặp trong trường hợp này sẽ là một kiểu giá trị và được sao chép, ví dụ:

// Warning: Does not compile 
foreach (int i in ints) 
{ 
    ++i; // Would not change the int in ints 
} 

Thậm chí nếu biến lặp là một loại tài liệu tham khảo, có hoạt động trở lại một đối tượng mới, bạn sẽ không bị thay đổi bộ sưu tập ban đầu, bạn sẽ chỉ được giao lại cho biến này phần lớn thời gian:

// Warning: Does not compile 
foreach (MyClass ob in objs) 
{ 
    ob=ob+ob; // Reassigning to local ob, not changing the one from the original 
      // collection of objs 
} 

Ví dụ sau đây có khả năng để thực sự cải tiến đối tượng trong bộ sưu tập ban đầu bằng cách gọi một phương pháp đột biến:

// Warning: Does not compile 
foreach (MyClass ob in objs) 
{ 
    ob.ChangeMe(); // This could modify the object in the original collection 
} 

Để tránh nhầm lẫn liên quan đến giá trị so với các loại tài liệu tham khảo với và các kịch bản nêu trên (cùng với một số lý do liên quan đến tối ưu hóa), MS đã chọn tạo biến số lặp lại readonly.

1

foreach được thiết kế để truy cập từng mục trong bộ sưu tập chính xác một lần và không sử dụng "chỉ số vòng lặp" rõ ràng; nếu bạn muốn kiểm soát nhiều hơn vòng lặp và có chỉ số vòng lặp, hãy sử dụng for.

EDIT: Bạn có thể thay đổi các mục trong bộ sưu tập đang được lặp lại bên trong vòng lặp foreach. Ví dụ:

foreach(Chair ch in mychairs) 
{ 
    ch.PaintColour = Colour.Green; //this alters the chair object *in* the collection. 
} 

Bạn không thể thêm hoặc xóa các mục vào/ra khỏi bộ sưu tập.

+0

Thực ra, bạn không thể sửa đổi một trường/thuộc tính của đối tượng được tham chiếu bởi biến lặp lại. –

+0

@Michael: Mã tôi đăng hoạt động OK cho tôi. Tôi đang sử dụng .NET 3.5 và Visual Studio 2008. – CesarGon

7

Vì phần tử hiện tại được trả về theo giá trị (ví dụ: sao chép). Và sửa đổi bản sao là vô ích. Nếu đó là loại tham chiếu, bạn có thể sửa đổi nội dung của đối tượng đó, nhưng không thể thay thế tham chiếu.

Có lẽ bạn nên đọc tài liệu của IEnumerable<T>IEnumerator<T>. Điều đó sẽ làm cho nó rõ ràng hơn. Bit quan trọng nhất là IEnumerable<T> có thuộc tính Current thuộc loại T. Và tài sản này chỉ có một getter, nhưng không có setter.

Nhưng điều gì sẽ xảy ra nếu nó có người đặt cược?

  • Nó sẽ làm việc tốt với mảng và Lists
  • Nó sẽ không làm việc tốt với container phức tạp như hashtables, danh sách đặt hàng vì sự thay đổi gây ra những thay đổi lớn trong các thùng chứa (ví dụ như một sắp xếp lại), và do đó làm mất hiệu lực trình lặp. (Hầu hết các bộ sưu tập làm mất hiệu lực các trình vòng lặp nếu chúng được sửa đổi để tránh trạng thái không nhất quán trong các trình vòng lặp.)
  • Trong LINQ nó không có ý nghĩa gì cả. Ví dụ với select(x=>f(x)) giá trị là kết quả của một hàm và không có bộ nhớ vĩnh viễn nào được liên kết.
  • Với lặp bằng văn bản với các yield return cú pháp nó không có ý nghĩa hoặc
+0

"Và sửa đổi bản sao là vô ích." Nếu tôi muốn làm một cái gì đó giống như tổng bình phương của tất cả các số trong một danh sách? Nó có thể được thực hiện với các hạn chế chỉ đọc, nhưng nó thường hữu ích để sửa đổi một bản sao. – raylu

Các vấn đề liên quan