2010-09-26 22 views
7

Tôi đã viết một lớp thực hiện IEnumerable<T>. Tôi có một phương thức trả về MyClass. Nếu tôi cố gắng yield return từ bên trong phương thức đó, trình biên dịch cho tôi biết "... không thể là khối lặp bởi vì ... không phải là loại giao diện trình lặp".Làm cách nào để xác định loại giao diện trình lặp?

Vì vậy, làm cách nào tôi có thể xác định loại trình vòng lặp giao diện của riêng mình? Nó có phải là "trừu tượng" (không thể có bất kỳ phương pháp nào được định nghĩa) không?

Những gì tôi muốn làm là viết một loạt các phương pháp có thể chuỗi, vì vậy mọi phương thức sẽ trả về một thể hiện của MyClass. Nhưng tôi cần MyClass để được một số loại enumerable. Thay vì sử dụng một số loại dữ liệu cơ bản, tôi đã hy vọng tôi chỉ có thể yield return ở mọi nơi.


@Oded:

class SharpQuery : IEnumerable<HtmlNode> 
{ 
    public SharpQuery Find(string selector) 
    { 
     foreach (var n in this) 
     { 
      // filter the results 
      yield return node; 
     } 
    } 
} 
+1

Bạn có thể đăng các bit liên quan của mã không? – Oded

Trả lời

10

Không, đó là không thể. Để xem lý do tại sao hãy xem xét rằng bạn có một lớp học Zoo thực hiện IEnumerable<Animal> nhưng cũng có rất nhiều thành viên khác. A Zoo là một số IEnumerable<Animal> nhưng không nhất thiết ngược lại - một chuỗi động vật chỉ là một chuỗi các động vật. Không có người quản lý vườn thú, không có cửa hàng, không có phí vào cửa hay bất kỳ thứ gì khác khiến vườn thú trở thành sở thú.

Khi bạn sử dụng yield return x loại trả về không thể là Zoo vì bạn không có sở thú - bạn chỉ có một chuỗi động vật.

gì bạn có thể làm thay vào đó là để gọi nó như new Zoo(foo()) nơi foo trả về một IEnumerable<Animal> và thêm một constructor để Zoo chấp nhận một IEnumerable<Animal>.

+0

Ngay cả khi 'Zoo' không có bất kỳ dữ liệu nào, chỉ cần phương pháp? – mpen

+2

Nếu bạn chỉ có phương pháp, bạn có thể thực hiện chúng như là các phương pháp mở rộng trên 'IEnumerable '. Sau đó, tôi nghĩ rằng bạn có được những gì bạn muốn - bạn có thể dễ dàng sử dụng năng suất, và bạn có thể có các phương pháp chuyên biệt về trình tự của bạn. –

+0

Tôi cần một nhà xây dựng mặc dù ... mà sẽ mang lại chỉ là một mục tôi đoán. Sau đó, tôi đoán tôi chỉ có thể sử dụng một chức năng công cộng cho rằng thay vào đó. Tôi phải suy nghĩ về điều này nhiều hơn một chút ... nếu tôi thực sự muốn ép buộc bản thân mình vào một lớp không trạng thái ... đó là một ý tưởng gọn gàng. Cảm ơn! – mpen

2

Tôi nghĩ rằng khi bạn sử dụng yield return x, bạn sẽ sản xuất một loại IEnumerable loại X. Vì vậy, trong trường hợp của bạn, nó sẽ là IEnumerable

Thừa kế từ một lớp sẽ không tự động có nghĩa là nó sẽ tự ẩn hoàn toàn với loại đó. Vì vậy, nếu bạn viết

class SharpQuery 
{ 
    public IEnumerable<HtmlNode> RepositoryItems { get; set; } 
    public IEnumerable<HtmlNode> Find(string selector) 
    { 
     foreach (var n in this.RepositoryItems) 
     { 
      // filter the results 
      yield return node; 
     } 
    } 
} 

hoạt động. IEnumerable không giống với SharpQuery.

+0

Điều này không hoạt động vì HtmlNode không được xác định. – user1789573

+0

Bắt tốt. Có thực sự nó là một phiên bản tước. SharpQuery không thực hiện IEnumerable thực sự, nhưng sự trở lại của Find sẽ hoạt động. Tôi đã sửa nó. – abhishek

2

Theo mục 8.2 của C# Language Specification Version 4.0:

Một khối có chứa một hoặc nhiều yield báo cáo được gọi là một khối iterator. Các khối Iterator được sử dụng để thực thi các thành viên hàm như các trình vòng lặp.

Mục 10,14 xác định rằng kiểu trả về của một iterator phải là một trong những điều sau đây:

  • IEnumerator
  • IEnumerable
  • IEnumerator<T>
  • IEnumerable<T>

Theo mục 10.14.4, gọi một trình lặp không thực hiện ngay lập tức mã trong khối lặp. Thay vào đó, một đối tượng điều tra viên mà thực hiện các giao diện sau đây được tạo ra và trả về:

  • IEnumerator
  • IEnumerator<T>
  • IDisposable

Đối tượng điều tra viên thường là một thể hiện của một lớp lồng nhau trình biên dịch tạo với khả năng truy cập riêng tư.

+0

Tôi nghĩ rằng tôi muốn trả lại một cái gì đó thực hiện một trong những giao diện, chứ không phải là giao diện chính nó. – mpen

+0

Mỗi https://msdn.microsoft.com/en-us/library/ms228593.aspx thông số C# được cài đặt với Visual Studio trong 'Program Files (x86)/Microsoft Visual Studio 12.0/VC#/Thông số kỹ thuật/1033'. Thay đổi phiên bản studio trực quan phù hợp, 14.0 cho VS2015, v.v. – BurnsBA

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