Từ những gì tôi đã đọc, quyết định thiết kế đã được thực hiện cho một số loại Bộ sưu tập nhất định là cấu trúc có thể thay đổi thay vì loại tham chiếu vì lý do hiệu suất.
Câu hỏi hay.
Trước hết, bạn đã chính xác. Mặc dù nói chung, các loại giá trị có thể thay đổi là một mã có mùi xấu, trong trường hợp này chúng được hợp lý:
- Biến đổi gần như hoàn toàn bị ẩn khỏi người dùng.
- Rất khó có ai sẽ sử dụng điều tra theo cách khó hiểu.
- Việc sử dụng loại giá trị có thể thay đổi thực sự giải quyết được vấn đề hiệu năng thực tế trong trường hợp cực kỳ phổ biến.
tôi tự hỏi nếu có ai biết lý do tại sao iterator generic Array Avatar của đã được thực hiện như một loại tài liệu tham khảo khi rất nhiều bộ sưu tập quan trọng hiệu suất khác sử dụng cấu trúc có thể thay đổi để thay thế.
Vì nếu bạn là loại người quan tâm đến hiệu suất liệt kê một mảng thì tại sao bạn sử dụng điều tra viên ở nơi đầu tiên? Đó là một mảng vì lợi ích của thiên đàng; chỉ cần viết một vòng lặp for
lặp lại các chỉ báo của nó như một người bình thường và không bao giờ phân bổ điều tra viên. (Hoặc một foreach
loop; # trình biên dịch C sẽ viết lại foreach
loop vào for
vòng lặp tương đương nếu nó biết rằng bộ sưu tập vòng lặp là một mảng.)
Lý do duy nhất lý do tại sao bạn muốn có được một Enumerator từ một mảng trong vị trí đầu tiên là nếu bạn đang chuyển nó đến một phương thức có một số IEnumerator<T>
, trong trường hợp này là nếu điều tra viên là một cấu trúc thì bạn sẽ được boxing nó. Tại sao phải chịu chi phí làm cho loại giá trị và sau đó đấm bốc nó? Chỉ cần biến nó trở thành kiểu tham chiếu để bắt đầu.
Nguồn
2012-02-07 21:15:15
Với sự phổ biến (và sức mạnh biểu cảm) của LINQ, các điều tra viên có khả năng được truy xuất cho các mảng khá thường xuyên. Ví dụ, các lớp phản chiếu trong các mảng trả về .NET cho nhiều thuộc tính/phương thức - và sử dụng LINQ w/reflection khá tiện dụng. Theo hiểu biết của tôi, hầu hết các toán tử LINQ không thực hiện các kiểm tra trường hợp đặc biệt để xác định xem IEnumerable <> chúng đang xử lý thực sự là một mảng hay không. – LBushkin
@LBushkin: Đúng. Nếu bạn không muốn nhận chi phí phân bổ heap và sau đó thu gom rác * enumerator * thì bạn cũng có lẽ không muốn chi phí phân bổ đống và thu gom rác * truy vấn *, và tất cả các đối tượng liệt kê nó tạo ra và tất cả các đại biểu bạn phải tạo. Không phải đề cập đến tất cả các chi phí của việc gọi truy vấn đó (kiểm tra đối số cho là chính xác, và như vậy). LINQ cho các đối tượng là biểu diễn hợp lý nhưng chắc chắn nó không được thiết kế để giảm thiểu phân bổ đống! LINQ phân bổ bộ nhớ heap khắp nơi. –
Một yếu tố khác, tôi nghi ngờ, đó là điều tra cho bản gốc 'Danh sách' được thiết kế trong những ngày trước khi Generics. Cấu trúc-Ness của 'List.Enumerator' chỉ ảnh hưởng đến ba loại mã: mã sử dụng rõ ràng kiểu' List.Enumerator', mã chấp nhận tham số chung bị ràng buộc với 'IEnumerable', hoặc mã sử dụng' var' để khai báo biến sẽ giữ bảng liệt kê của một danh sách. Nếu một lập trình viên sẽ chỉ định 'List.Enumerator', lập trình viên nên biết những gì anh ta đang làm. Đối với hai loại mã khác, chúng không thể tồn tại khi 'List.Enumerator' được thiết kế. – supercat