Một vòng lặp foreach dường như tạo ra một đối tượng IEnumerator ra khỏi bộ sưu tập mà bạn vượt qua nó, và sau đó đi qua đó. Vì vậy, một vòng lặp như thế này:
foreach(var entry in collection)
{
entry.doThing();
}
dịch sang một cái gì đó giống như thế này:
(gợi ra một số phức tạp xung quanh cách liệt kê được xử lý sau này)
var enumerator = collection.GetEnumerator();
while(enumerator.MoveNext()) {
var entry = enumerator.Current;
entry.doThing();
}
Nếu điều này được biên dịch một cách ngây thơ / trực tiếp, thì đối tượng liệt kê đó sẽ được phân bổ trên heap (mất một ít thời gian), ngay cả khi kiểu cơ bản của nó là một cấu trúc - thứ gọi là quyền anh. Sau khi hoàn thành vòng lặp, phân bổ này sẽ trở thành rác để dọn dẹp sau đó và trò chơi của bạn có thể bị trì hoãn trong giây lát nếu đủ rác chất đống để người thu gom chạy quét toàn bộ. Cuối cùng, MoveNext
phương thức và thuộc Current
tính có thể bao gồm nhiều bước gọi hàm hơn là chỉ lấy một mục trực tiếp collection[i]
, nếu trình biên dịch không thực hiện hành động đó.
Các liên kết Hellium tài liệu Hellium ở trên chỉ ra rằng hình thức ngây thơ này chính xác là những gì xảy ra trong Unity trước phiên bản 5.5 , nếu lặp lại bất cứ điều gì khác ngoài Mảng bản địa.
Trong phiên bản 5.6+ (bao gồm cả phiên bản 2017), quyền anh không cần thiết này đã biến mất và bạn không nên trải nghiệm sự phân bổ không cần thiết nếu bạn đang sử dụng bất kỳ loại cụ thể nào (ví dụ: int[]
hoặc List<GameObject>
hoặc Queue<T>
).
Bạn vẫn sẽ nhận được phân bổ nếu phương thức được đề cập chỉ biết rằng nó hoạt động với một loại IList hoặc giao diện khác - trong những trường hợp đó, nó không biết trình liệt kê cụ thể nào nó hoạt động để nó phải đưa nó vào đối tượng IEnumerator trước .
Vì vậy, rất có thể đây là lời khuyên cũ không quá quan trọng trong phát triển Unity hiện đại. Các nhà phát triển đoàn kết như chúng ta có thể hơi mê tín về những thứ từng là chậm / nhiều lông trong các phiên bản cũ, vì vậy hãy đưa ra bất kỳ lời khuyên nào về hình thức đó với một hạt muối. ;) Động cơ phát triển nhanh hơn niềm tin của chúng tôi về nó.
Trong thực tế, tôi chưa bao giờ có một triển lãm trò chơi chậm chạp đáng chú ý hoặc trục trặc thu gom rác từ việc sử dụng các vòng lặp foreach, nhưng số dặm của bạn có thể thay đổi. Hồ sơ trò chơi của bạn trên phần cứng đã chọn của bạn để xem liệu nó có đáng lo ngại không. Nếu bạn cần, việc thay thế các vòng lặp foreach thành các vòng lặp rõ ràng sau này trong quá trình phát triển sẽ là một vấn đề, vì vậy tôi sẽ không hy sinh tính dễ đọc và dễ mã hóa sớm trong quá trình phát triển.