2010-08-08 30 views
5

Tôi có thể thêm các nút một cách an toàn vào vùng chứa LinkedList bên trong câu lệnh foreach không? Có bất kỳ sự khác biệt nếu tôi sử dụng trong khi vòng lặp? Hoặc nó không bao giờ được cho phép và có thể gây ra một số vấn đề?Thêm các nút vào LinkedList <T> trong foreach

foreach(var node in myList) 
{ 
    if(condition) 
     myList.AddLast(new MyNode()); 
} 

Liệu nó luôn luôn hoạt động?

Trả lời

6

Bạn không thể sửa đổi bộ sưu tập khi đang liệt kê nó.

Từ docs for LinkedList<T>.GetEnumerator:

Một điều tra viên vẫn có giá trị càng lâu càng bộ sưu tập vẫn không thay đổi. Nếu thay đổi được thực hiện cho bộ sưu tập, chẳng hạn như thêm, sửa đổi hoặc xóa yếu tố, điều tra viên là không hợp lệ vô hiệu và hành vi của chúng tôi là không xác định.

Trong thực tế, tôi tin rằng nó sẽ luôn ném một InvalidOperationException, mặc dù hành vi chính thức không được xác định.

EDIT: Bạn hỏi trong một chú thích cho dù một vòng lặp while sẽ giúp ... một vòng lặp trong khi sử dụng GetEnumerator/MoveNext/Current sẽ không, nhưng điều này sẽ:

LinkedListNode<MyNode> current = myList.First; 
while (current != null) 
{ 
    if (condition) // use current.Value to get the value 
    { 
     myList.AddLast(new MyNode()); 
    } 
    current = current.Next; 
} 

Theo như tôi nhận thức, điều đó hoàn toàn an toàn và có thể dự đoán được. Bạn luôn có thể yêu cầu một nút cho nút tiếp theo của nó. Nếu bạn tình cờ nhìn vào nút đuôi và thêm nút khác, bạn sẽ nhận được nút đuôi mới khi bạn yêu cầu "tiếp theo".

Nếu điều đó không có tác dụng, vui lòng cung cấp cho chúng tôi thêm chi tiết về những gì bạn đang cố gắng đạt được.

+0

Hoàn toàn an toàn là một vòng lặp vô tận, căng thẳng và OOM nếu nút mới khớp với điều kiện. –

1

Trong khi lặp qua bộ sưu tập với tuyên bố foreach, bạn không thể sửa đổi nó. Do đó, việc thêm các mục sẽ dẫn đến lỗi trình biên dịch.

+0

sẽ sử dụng vòng lặp 'while' giải quyết được sự cố của mình? –

+1

Bạn có thể sử dụng vòng lặp 'while' để lặp qua bộ sưu tập. Bạn sẽ không nhận được lỗi biên dịch khi thực hiện việc này, nhưng hãy cẩn thận không viết một vòng lặp vô hạn - điều này có thể xảy ra nếu 'MyNode()' mới đáp ứng 'điều kiện'. –

+3

Nó * sẽ không * dẫn đến lỗi trình biên dịch. Mã được đưa ra sẽ biên dịch không có vấn đề gì. Nó sẽ ném một ngoại lệ tại thời gian thực hiện. –

2

Không, đối tượng liệt kê ghi nhớ phiên bản nội bộ của bộ sưu tập. Sau khi bộ sưu tập được sửa đổi - phiên bản đã thay đổi, do đó, foreach sẽ không thành công.

+0

+1 Để xem nhanh với phản xạ để xem cách các điều tra viên đang thực hiện kiểm tra :) – Ani

0

Có lẽ bạn có thể thêm chúng vào danh sách mới. Sau đó, ở cuối, bên ngoài foreach sử dụng .addrange() để nối các danh sách mới vào danh sách gốc.

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