Về cơ bản, giao diện nongeneric xuất hiện trước, trong .NET 1.0 và 1.1. Sau đó, khi .NET 2.0 ra đời, các tương đương chung xuất hiện. Cuộc sống có thể đã được đơn giản hơn rất nhiều nếu Generics đã làm cho nó vào NET 1.0 :)
Xét về thực hiện "chỉ" IEnumerable<T>
thay vì cả hai - về cơ bản bạn có để thực hiện cả hai, và bạn phải sử dụng giao diện rõ ràng thực hiện quá, cho rằng cả hai xác định một phương pháp không tham số GetEnumerator
. Như IEnumerator<T>
kéo dài IEnumerator
quá, đó là bình thường một cái gì đó như thế này:
public IEnumerator<T> GetEnumerator()
{
// Return real iterator
}
// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
// Delegate to the generic implementation
return GetEnumerator();
}
Mặt khác, với các khối iterator giới thiệu trong C# 2 (với yield return
vv), bạn hiếm khi cần phải thực hiện những điều này hoàn toàn bằng tay, may mắn thay. Bạn có thể cần phải viết một cái gì đó như trên, và sau đó sử dụng yield return
trong phương pháp GetEnumerator
.
Lưu ý rằng IList<T>
không không mở rộng IList
, và ICollection<T>
không không mở rộng ICollection
. Đó là bởi vì nó ít an toàn hơn để làm như vậy ... trong khi bất kỳ trình vòng lặp chung nào có thể được xem như là một trình lặp không đồng bộ do chuyển đổi (có khả năng đấm bốc) của bất kỳ giá trị nào thành object
, IList
và ICollection
cho phép các giá trị được thêm vào bộ sưu tập; và không có ý nghĩa gì khi thêm (nói) một chuỗi vào một số IList<int>
.
EDIT: Lý do tại sao chúng tôi cần IEnumerable<T>
để chúng tôi có thể lặp lại theo cách an toàn, và truyền bá thông tin đó. Nếu tôi trả lại một số IEnumerable<string>
cho bạn, bạn biết rằng bạn có thể giả định một cách an toàn mọi thứ được trả lại từ đó sẽ là tham chiếu chuỗi hoặc null. Với IEnumerable
, chúng tôi phải đúc một cách hiệu quả (thường ngầm trong câu lệnh foreach
) mỗi phần tử được trả lại từ chuỗi, vì thuộc tính Current
của IEnumerator
chỉ là loại object
.Đối với lý do tại sao chúng tôi vẫn còn cần IEnumerable
- về cơ bản vì giao diện cũ không bao giờ biến mất. Có quá nhiều mã đang sử dụng.
Nó đã có thể cho IEnumerable<T>
không để kéo dài IEnumerable
, nhưng sau đó bất kỳ mã muốn tận dụng một IEnumerable<T>
không thể gọi thành một phương pháp chấp nhận IEnumerable
- và đã có rất nhiều các phương pháp như thế từ .NET 1.1 và 1.0.
+1 Cuộc sống sẽ đơn giản hơn rất nhiều nếu các generics đã tạo ra nó thành .NET 1.0 ... – Oded
@Jon: câu hỏi đặt ra là: tại sao chúng ta cần phải thực hiện 'IEnumerable' khi chúng ta đã thực hiện 'IEnumerable' , hoặc ngược lại? –
Nawaz
@Nawaz: Tôi đã chỉnh sửa câu trả lời của mình. Làm thế nào thoải mái là bạn với ý tưởng về lý do tại sao Generics là một điều tốt? –