Danh sách <T> là một lớp và thực hiện cả giao diện ICollection <T> và IEnumerable <T> . Ngoài ra, ICollection <T> mở rộng giao diện <T> IEnumerable. Chúng không thể thay thế cho nhau, ít nhất là không phải từ tất cả các quan điểm.
Nếu bạn có Danh sách <T>, bạn được đảm bảo rằng đối tượng này thực hiện các phương thức và thuộc tính bắt buộc phải được thực hiện bởi giao diện ICollection <T> và IEnumerable <T>. Trình biên dịch biết điều đó và bạn được phép bỏ "xuống" một ICollection <T> hoặc IEnumerable <T>. Tuy nhiên, nếu bạn có ICollection <T>, trước tiên bạn phải kiểm tra rõ ràng mã của mình cho dù đó là Danh sách <T> hay thứ gì khác, có lẽ là Từ điển <T> (trong đó T là KeyValuePair ) trước khi chuyển nó thành gì khao khát.
Bạn biết rằng ICollection mở rộng IEnumerable, vì vậy bạn có thể bỏ nó xuống IEnumerable. Nhưng nếu bạn chỉ có một IEnumerable, một lần nữa bạn không được đảm bảo rằng đó là Danh sách. Nó có thể, nhưng nó có thể là một cái gì đó khác. Bạn nên mong đợi một ngoại lệ truyền không hợp lệ nếu bạn cố gắng đưa Danh sách <T> sang Từ điển <T> chẳng hạn.
Vì vậy, chúng không "hoán đổi cho nhau".
Ngoài ra, có rất nhiều giao diện chung, hãy kiểm tra những gì bạn có thể tìm thấy trong không gian tên System.Collections.Generic .
Chỉnh sửa: liên quan đến nhận xét của bạn, hoàn toàn không có hình phạt về hiệu suất nếu bạn sử dụng Danh sách <T> hoặc một trong các giao diện mà nó thực hiện. Bạn vẫn sẽ cần tạo một đối tượng mới, kiểm tra đoạn mã sau:
List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;
list , myColl và myEnum đều trỏ đến cùng một đối tượng. Cho dù bạn khai báo nó dưới dạng Danh sách hay ICollection hay IEnumerable tôi vẫn yêu cầu chương trình tạo Danh sách. Tôi có thể đã viết điều này:
ICollection<T> myColl = new List<T>();
myColl , tại thời gian chạy vẫn là một Danh sách.
Tuy nhiên , đây là điểm quan trọng nhất ... để giảm khớp nối và tăng khả năng bảo trì, bạn nên luôn luôn khai báo các biến và tham số phương thức bằng cách sử dụng mẫu số thấp nhất có thể cho bạn, cho dù đó là giao diện hay lớp trừu tượng hay cụ thể.
Hãy tưởng tượng rằng điều duy nhất mà phương thức "PerformanceOperation" cần là liệt kê các phần tử, thực hiện một số công việc và thoát, trong trường hợp đó bạn không cần thêm hàng trăm phương thức có sẵn trong Danh sách <T>, bạn chỉ cần những gì có sẵn trong IEn Countable <T >, vì vậy những điều sau đây nên được áp dụng:
public void PerformOperation(IEnumerable<T> myEnumeration) { ... }
Bằng cách đó, bạn và các nhà phát triển khác biết rằng bất kỳ đối tượng nào của lớp đang thực hiện giao diện <T> IEnumerable đều có thể được cung cấp cho phương thức này. Nó có thể là Danh sách, Từ điển hoặc lớp bộ sưu tập tùy chỉnh mà nhà phát triển khác đã viết.
Nếu ngược lại, bạn xác định rõ ràng bạn cần một Danh sách cụ thể <T> (và mặc dù hiếm khi xảy ra trong cuộc sống thực, nó vẫn có thể xảy ra), bạn và các nhà phát triển khác biết rằng đó phải là Danh sách hoặc một lớp cụ thể khác kế thừa từ Danh sách.