2012-03-23 64 views
5

Trong nhiều dự án của chúng tôi, tôi đã thấy một vài lớp sưu tập hoặc vùng chứa tùy chỉnh chứa một số loại bộ sưu tập chung chung, ví dụ: một lớp học List(of T).Khi nào bạn nên sử dụng IEnumerable và GetEnumerator?

Chúng thường có phương thức GetXXX trả về một IEnumerable của bất kỳ loại lớp sưu tập tùy chỉnh nào sử dụng để thu thập nội bộ có thể được lặp lại xung quanh bằng cách sử dụng vòng lặp foreach.

ví dụ:

public IEnumerable<UploadState> GetStates 
{ 
    get 
    { 
     return new List<UploadState>(m_states); 
    } 
} 

Câu hỏi của tôi là nên những lớp học thay vì thực hiện các giao diện IEnumerable, và gọi GetEnumerator vào danh sách riêng của mình.

Có cách nào ưu tiên hoặc là tùy thuộc vào nhà phát triển không?

+1

Loại m_states là gì? Chỉ cần tự hỏi tại sao nó được bao bọc bởi 'Danh sách mới <>' và được trả về là 'IEnumerable <> ' – sll

+0

http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator.aspx –

Trả lời

2

Nếu lớp học của bạn là lớp sưu tập tùy chỉnh thì có, cần triển khai IEnumerable<T>. Trong trường hợp này, một thuộc tính công khai cho danh sách bên trong sẽ là thừa.Hãy tưởng tượng một lớp đơn giản:

public class People : IEnumerable<Person> 
{ 
    List<Person> persons = new List<Person>(); 

    public IEnumerator<Person> GetEnumerator() 
    { 
     return persons.GetEnumerator(); 
    } 
} 

Nhưng nếu lớp học của bạn không thể hoạt động như một bộ sưu tập sau đó cung cấp một công IEnumerable tài sản cho các yếu tố của nó:

public class Flight 
{ 
    List<Person> passengers = new List<Person>(); 

    public IEnumerable<Person> Passengers 
    { 
     get { return passengers; } 
    } 
} 

Dù sao, nó luôn được các nhà phát triển để lựa chọn bên phải thiết kế.

+0

Cảm ơn Balazs Tihanyi, tôi có thể hỏi một câu hỏi ngớ ngẩn về ví dụ của bạn, tại sao bạn thực hiện từ IEnumerable chứ không phải IEnumberble? Tôi không chắc. – bobbo

+0

Tại sao bạn muốn? 'IEnumerable ' là chung và loại an toàn. 'IEnumerable' là dành cho .NET 1.1 hoặc các kiểu ẩn danh. Nếu bạn chỉ thực hiện giao diện 'IEnumerable', bạn sẽ phải đưa các mục danh sách của mình vào kiểu của chúng. –

2

tôi sẽ làm điều đó theo cách đó:

public IEnumerable<UploadState> GetStates 
{ 
    get 
    { 
     foreach (var state in m_states) { 
      yield return state; 
     } 
    } 
} 

Nó là sạch hơn, người dùng của bạn không có được một danh sách mà họ không nên (họ có thể bỏ nó vào một List<T> sau khi tất cả) và bạn don' t cần phải tạo một đối tượng List<T>.

EDIT: Hiểu sai câu hỏi. Tôi nghĩ rằng nếu lớp học có nghĩa là một bộ sưu tập, nó nên thực hiện IEnumerable<T>.

+0

Tôi tin rằng đây không phải là yêu cầu ở đây vì vậy nó có thể là một bình luận không phải là một câu trả lời, nhưng dù sao cũng có ý nghĩa từ việc tái cấu trúc quan điểm – sll

0

Bạn nên tạo các lớp sưu tập tùy chỉnh của mình dựa trên một trong các lớp trong không gian tên System.Collections.ObjectModel. Chúng đã chứa các triển khai của IEnumerable<T> và giao diện IEnumerable không chung.

1

Hãy xem xét trong ví dụ mã của bạn, hãy tạo mới danh sách được tạo. Tôi không biết m_states là gì, nhưng nếu đây là bộ sưu tập loại giá trị, bạn tạo một bản sao của danh sách gốc. Bằng cách này, danh sách trả về có thể được điều khiển tạo thành các phần tử Add/Remove/Update của người gọi. mà không cần ảnh hưởng đến dữ liệu gốc.

Nếu m_states nhiều loại tài liệu tham khảo, đây vẫn tạo ra một danh sách mới có thể một lần nữa thao túng bởi người gọi Add/Remove/Không yếu tố cập nhật (đó là một tài liệu tham khảo!) Mà không ảnh hưởng dữ liệu gốc.

Điều gì về IEnumerable<T>, nó chỉ là một cách để tạo kiểu trả về chung chung và không tạo khớp nối mạnh với loại List<T>.

+0

m_states là một kiểu tham chiếu. Được tuyên bố là Danh sách riêng m_states = new List (); Tôi nghĩ rằng phương thức trả về không thể được thao tác vì trả về một số điện thoại có thể truy cập được là , không phải là Danh sách ? – bobbo

+0

@bobbo: chắc chắn nó ** có thể **, nếu bạn chọn một phần tử từ bộ sưu tập trả về và thay đổi thuộc tính của nó, bạn thay đổi thuộc tính của phần tử ** gốc ** vì đây là loại * tham chiếu *. – Tigran

+0

OK, điều đó có ý nghĩa. Tuy nhiên, câu của bạn "Nếu m_states là kiểu tham chiếu, điều này vẫn tạo ra một danh sách mới có thể được điều khiển bởi người gọi Add/Remove/No update elements (tham chiếu!) Mà không ảnh hưởng đến dữ liệu gốc." thật khó hiểu. Bạn có nghĩa là danh sách mới được trả về có thể được thêm vào và các phần tử có thể bị xóa nhưng không có cập nhật nào không? Tôi nghĩ rằng bởi vì nó trả về ienumerable bạn có thể sửa đổi các yếu tố trong danh sách, tức là thay đổi một tài sản như bạn nói nhưng bạn không thể thêm và loại bỏ các mục trong danh sách. Đúng không? – bobbo

0

Tôi nghĩ rằng nếu lớp mới được triển khai của bạn chỉ hoạt động như một danh sách, thì không cần phải triển khai nó. Nếu bạn cần một số loại logic tùy chỉnh, nó phụ thuộc vào những gì bạn muốn làm; bạn có thể kế thừa danh sách hoặc bạn có thể thực hiện IEnumerable. Nó chỉ phụ thuộc vào những gì đạt được.

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