2009-04-19 82 views

Trả lời

80

IEnumerable chỉ cung cấp chức năng "lặp lại" tối thiểu. Bạn có thể duyệt qua chuỗi, nhưng đó là về nó. Điều này có nhược điểm - ví dụ, không hiệu quả khi đếm các phần tử bằng IEnumerable, hoặc để lấy phần tử thứ n - nhưng nó cũng có lợi thế - ví dụ, một IEnumerable có thể là một chuỗi vô tận, giống như dãy số nguyên tố.

Mảng là bộ sưu tập có kích thước cố định với quyền truy cập ngẫu nhiên (nghĩa là bạn có thể lập chỉ mục vào đó).

Danh sách là bộ sưu tập có kích thước biến (tức là bạn có thể thêm và xóa các phần tử) với quyền truy cập ngẫu nhiên.

IList là một giao diện mà tóm tắt chức năng danh sách (đếm, thêm, xóa, truy cập indexer) ra khỏi lớp bê tông khác nhau như List, BindingList, ObservableCollection vv

+2

Theo câu trả lời được chấp nhận ở đây http://stackoverflow.com/questions/1826658/what-is-faster-or-preferred-ienumerable-toarray-or-tolist. Đếm trên IEnumerable gần như cùng một beacuse nó cố gắng gọi Count trên ICollection – Karsten

+12

Có và không. Phương thức mở rộng Count() kiểm tra nếu IEnumerable cũng là một ICollection, và gọi thuộc tính Count của nó nếu nó là. Nếu IEnumerable * không phải là * một ICollection thì Count() giảm trở lại để lặp lại chuỗi. Có lẽ tôi nên nói "không hiệu quả khi đếm các phần tử bằng cách sử dụng * chỉ * IEnumerable", bởi vì tất nhiên sự hiện diện của IEnumerable không ngăn bạn sử dụng một phương pháp hiệu quả hơn nếu đối tượng có một, và các phương thức mở rộng LINQ to Objects làm chính xác điều đó. – itowlson

9

IEnumerable và IList là interfaces. Mảng và Danh sách là các lớp. Array triển khai IEnumerable. Danh sách thực hiện IList mở rộng IEnumerable.

Chỉnh sửa: như itowlson được đề cập trong nhận xét, Array cũng triển khai IList.

+4

Mảng cũng thực hiện IList. – itowlson

+0

Tôi cũng vậy! Điều gì sẽ xảy ra nếu bạn bắt đầu gọi IList.RemoveAt trên một mảng, mặc dù? –

+0

Nó ném ra một NotSupportedException. (Lưu ý IList.RemoveAt và các phương thức IList tương tự được triển khai một cách rõ ràng trên Array sao cho chúng không hiển thị trên một tham chiếu Array bình thường!) – itowlson

13

IEnumerable là giao diện cho phép lặp qua bộ sưu tập các mục (ví dụ: thông qua từ khóa foreach).

Một mảng là nội tại .NET. Nó chứa các mục cùng loại, nhưng nó có kích thước cố định. Khi bạn tạo một mảng với các phần tử x, nó không thể phát triển hoặc thu nhỏ.

IList xác định giao diện cho danh sách và cũng triển khai IEnumerable.

Danh sách triển khai giao diện IList; nó là một loại cụ thể của danh sách.

Sự khác biệt giữa Danh sách .NET và các mảng là danh sách có thể có các phần tử được thêm vào chúng - chúng phát triển đủ lớn để chứa tất cả các mục được yêu cầu. Danh sách lưu trữ nội bộ này trong một mảng và, khi mảng không còn đủ lớn để chứa tất cả các phần tử, một mảng mới được tạo và các mục được sao chép trên đó.

IList & cả hai mảng đều triển khai IEnumerable. Đó là cách các giao diện làm việc - các lớp thực hiện hợp đồng và hành xử theo cách tương tự và có thể được xử lý tương tự như kết quả (bạn biết rằng lớp thực hiện IEnumerable, bạn không cần biết các hows hoặc whys). Tôi đề nghị bạn đọc lên trên giao diện và vv.

+1

Thêm nhận xét này cho người đọc không đọc tất cả các câu trả lời: mảng và Danh sách <> cả hai thực thi IList <> (mảng thực hiện nhiều nó rõ ràng, có lẽ vì nhiều thành viên ném NotSupportedException). Nó cũng chính xác hơn khi nói rằng IList kế thừa từ IEnumerable hơn là nói nó thực hiện nó. – phoog

2

IEnumerable là một giao diện có mục đích chung mà được nhiều lớp học sử dụng, chẳng hạn như Array, ListString để cho phép ai đó lặp qua bộ sưu tập. Về cơ bản, đó là những gì thúc đẩy tuyên bố foreach.

IList thường là cách bạn hiển thị các biến loại List cho người dùng cuối. Giao diện này cho phép truy cập ngẫu nhiên vào bộ sưu tập cơ bản.

6

Tạo bộ sưu tập IEnumerable là lười. Ví dụ:

public IEnumerable<int> GetTwoInts() 
{ 
    yield return 1; 
    yield return 2; 
} 
public void Something() 
{ 
    var twoInts = GetTwoInts(); 
} 

Trong phương pháp Something cuộc gọi đến GetTwoInts() sẽ không thực sự dẫn đến việc GetTwoInts phương pháp được thực hiện kể từ khi liệt kê không bao giờ lặp lại.

+0

Bạn có thể giải thích nó một chút không? Tôi không chắc liệu tôi có hiểu đúng không. Bạn có thể hiển thị một dòng mã sau đó sẽ thực sự dẫn đến phương thức đó đang được thực thi không? Cảm ơn! – paaone

+0

@paaone đặt 'haiInt' trong một' foreach' hoặc gọi 'twoInts.ToList()'. – row1

0

Đây là một bài đăng cũ, nhưng vẫn nghĩ đến trả lời. IEnumerable là một hành vi trong khi Array là một cấu trúc dữ liệu (Tập hợp các phần tử liền kề với kích thước cố định, tạo điều kiện truy cập các phần tử theo các chỉ mục). Khi một Array triển khai IEnumerable, nó được cho là mô tả thuộc tính vốn có của IEnumerable cũng (của việc tạo điều kiện lặp qua bộ sưu tập).

0

Để bổ sung cho các câu trả lời khác, lưu ý rằng có một sự khác biệt hiệu suất giữa IList<T>List<T> khi thực hiện tuyên bố foreach.

Đó là do đối tượng trình lặp được trả về List<T>.GetEnumerator là kiểu giá trị trong khi giá trị trả về IList<T>.GetEnumerator là kiểu tham chiếu và do đó yêu cầu cấp phát bộ nhớ (xem Enumerator of value type of list in c#).

Theo ý kiến ​​của tôi, IList<T> không phải là giao diện tốt lắm. Ví dụ, gọi Add có thể ném (xem Why array implements IList?). Nếu bạn cần đóng gói, bạn nên sử dụng IEnumerable<T> hoặc IReadOnlyList<T> tốt hơn.

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