Trước hết: thuật ngữ. Nếu bạn nói "danh sách rác", mọi người sẽ nghĩ bạn đang nói về người thu gom rác. Hãy gọi nó là "danh sách chết".
Như bạn có thể đã phát hiện ra, do đó, câu hỏi của bạn, bạn không thể xóa các mục khỏi bộ sưu tập trong khi bạn đang lặp qua nó. Nếu bộ sưu tập của bạn là một List<>
cách đơn giản nhất để xóa các mục khỏi nó là:
for(int i = list.Count-1; i >= 0; --i)
{
if(list[i].IsDead)
list.RemoveAt(i);
}
Lưu ý rằng bạn lặp đi lặp lại . Bạn có thể loại bỏ các mục trong khi lặp về phía trước, nhưng nó lộn xộn hơn và yêu cầu a goto
. Bạn không thể làm điều đó với foreach
.
Bạn có thể thực hiện loại bỏ riêng biệt từ vòng lặp cập nhật của bạn. Hoặc bạn có thể hợp nhất nó vào vòng cập nhật của bạn. Luôn luôn thực hiện RemoveAt
ở cuối vòng lặp - sau điểm đó trong vòng lặp, list[i]
không thể được coi là hợp lệ (nó sẽ trở lại hợp lệ trong lần lặp tiếp theo).
Ngoài ra, cũng lưu ý rằng mỗi đối tượng có IsDead
cờ riêng (nếu bạn đang sử dụng mẫu xử lý, bạn có thể tạo ra nó IsDisposed
) - bạn thực sự không cần phải duy trì một "danh sách chết".
Sử dụng cờ trên mỗi mục thích hợp hơn cho hiệu suất, vì bạn tránh phải tìm kiếm trong danh sách để xóa. Và nó cũng thích hợp hơn cho thiết kế - điều đó có nghĩa là mỗi đối tượng có thể dễ dàng kiểm tra xem nó đã chết chưa - vì vậy bạn không vô tình gọi bất kỳ phương thức nào trên đó (nếu các đối tượng này đang thực hiện mô hình dùng một lần, họ có thể ném ObjectDisposedException
trong trường hợp này).
Nếu bạn có một bộ sưu tập khác ngoài a List<>
, thì việc xóa các mục chết khỏi bộ sưu tập đó vẫn có thể liên quan đến việc tạo danh sách chết (vì việc xóa trong quá trình lặp có thể không thực hiện được). Theo tôi, nó đẹp hơn, thiết kế khôn ngoan hơn, để tạo danh sách chết ngay trước khi nó được sử dụng, bằng cách lặp qua bộ sưu tập tìm kiếm IsDead
cờ, thay vì cố gắng duy trì danh sách khi các đối tượng bị giết.
Một khi bạn đã hoàn thành với một danh sách chết, bạn nên giữ Clear()
nó, và sau đó giữ nó xung quanh để sử dụng lại sau này.