2010-07-05 15 views
5

xem xét mã này:Hiểu được mở rộng elementAt (index)

int size = 100 * 1000 * 1000; 
var emu = Enumerable.Range(0, size); 
var arr = Enumerable.Range(0, size).ToArray(); 

khi tôi gọi emu.ElementAt (size-10) và arr.ElementAt (size-10) và đo thời gian arr là nhanh hơn nhiều (mảng là 0,0002 so với IE9 có thể đếm được).

Theo tôi được biết, phương pháp gia hạn elementAt() có chữ ký

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index) 

và kể từ khi 'nguồn' là một IEnumerable logic thực hiện sẽ tương tự như - trái ngược với những gì tôi nhìn thấy nơi các mảng được truy cập trực tiếp.

Ai đó có thể xin giải thích này :)

Trả lời

5

Đây là một tối ưu hóa được thực hiện tại thời gian thực hiện. Mặc dù cuộc gọi không bị quá tải, nhưng nó có thể kiểm tra (sử dụng is hoặc as) cho dù nguồn thực sự là một IList<T>. Nếu có, nó có thể đi trực tiếp đến phần tử bên phải.

Các cuộc gọi khác thực hiện điều này - đáng chú ý Count() được tối ưu hóa cho ICollection<T> và (theo số .NET 4) giao diện nongeneric ICollection.

Một trong những nhược điểm của phương pháp mở rộng là tất cả các tối ưu hóa này phải được thực hiện bởi chính bản thân việc triển khai - loại không thể ghi đè bất kỳ thứ gì để "chọn tham gia" để tối ưu hóa các phương pháp mở rộng. Điều đó có nghĩa là tối ưu hóa tất cả phải được người triển khai gốc biết đến: (

+0

Bạn có thể gián tiếp chọn tham gia vào các tối ưu hóa bằng cách có kiểu bộ sưu tập tùy chỉnh của bạn thực hiện 'IList ', nhưng thực hiện nó một cách rõ ràng và/hoặc chỉ hiển thị công khai bộ sưu tập của bạn là 'IEnumerable '. Nếu bạn muốn, bạn có thể cung cấp một giao diện tùy chỉnh cho mỗi phương thức mở rộng tùy chỉnh cho phép một nhà văn lớp ghi đè hành vi của phương thức mở rộng, mặc dù điều này có thể hơi lộn xộn. (tiện ích con Widget này) 'và' WidgetExtensions.IToggleWidget '. –

12

Calling ElementAt trên một vòng lặp IEnumerable<T> chí qua các mục cho đến khi nó đạt đến chỉ số mong muốn. (Hoạt động An O (n))

Gọi ElementAt trên IList<T> (chẳng hạn như mảng) sẽ sử dụng chỉ mục của IList<T> để nhận ngay chỉ mục mong muốn. (Hoạt động An O (1))

+0

Arh, vì vậy bạn đang nói với tôi rằng ElementAt bị quá tải cho mảng, danh sách, điều gì không .. ?? – Moberg

+1

Nó không bị quá tải. – SLaks

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