Giải pháp hiện đại hơn
Trừ khi bạn cần bộ sưu tập nội bộ có thể thay đổi, bạn có thể sử dụng System.Collections.Immutable
gói, thay đổi loại trường của bạn thành một bộ sưu tập bất biến, và sau đó phơi bày điều đó trực tiếp - tất nhiên là giả sử Foo
nó là bất biến.
Cập nhật câu trả lời để giải quyết câu hỏi trực tiếp hơn
Có bất kỳ lý do nào để hiển thị một bộ sưu tập nội bộ dưới dạng ReadOnlyCollection chứ không phải là IEnumerable nếu mã cuộc gọi chỉ lặp lại trên bộ sưu tập?
Nó phụ thuộc vào mức độ bạn tin tưởng mã gọi. Nếu bạn hoàn toàn kiểm soát mọi thứ sẽ gọi thành viên này và bạn đảm bảo rằng sẽ không có mã nào sử dụng:
ICollection<Foo> evil = (ICollection<Foo>) bar.Foos;
evil.Add(...);
sau đó chắc chắn, sẽ không có hại gì nếu bạn trả lại bộ sưu tập trực tiếp. Tôi thường cố gắng để có một chút hoang tưởng hơn thế.
Tương tự như vậy, như bạn nói: nếu bạn chỉ cần IEnumerable<T>
, thì tại sao lại buộc mình vào bất cứ điều gì mạnh mẽ hơn?
Câu trả lời gốc
Nếu bạn đang sử dụng .NET 3.5, bạn có thể tránh tạo một bản sao và tránh việc truyền đơn giản bằng cách sử dụng một cuộc gọi đơn giản để Bỏ qua:
public IEnumerable<Foo> Foos {
get { return foos.Skip(0); }
}
(Có rất nhiều tùy chọn khác để gói một cách tầm thường - điều tuyệt vời về Skip
Chọn / Trường hợp không có đại biểu nào thực hiện vô nghĩa cho mỗi lần lặp.)
Nếu bạn không sử dụng .NET 3.5, bạn có thể viết một trình bao bọc rất đơn giản để làm điều tương tự:
public static IEnumerable<T> Wrapper<T>(IEnumerable<T> source)
{
foreach (T element in source)
{
yield return element;
}
}
ReadOnlyCollection
nếu bạn bị hoang tưởng, nhưng bây giờ bạn không bị ràng buộc với việc triển khai cụ thể.