2012-08-08 143 views
2

我一直想知道是否可以說State類實現IEnumerable<Person>IEnumerable<City>所以我可以通過foreach以及所有的城市,讓所有居住在該州的人。它甚至不會編譯這樣說:Error 1 'ConsoleApplication1.City' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'(怪異)...以下是代碼:C#實現泛型IEnumerable

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.Collections; 

namespace ConsoleApplication1 
{ 
    class Person 
    { 
    } 

    class City : IEnumerable<Person> 
    { 
     // City has citizens: 
     Person[] citizens; 

     IEnumerator<Person> IEnumerable<Person>.GetEnumerator() 
     { 
      foreach (Person p in citizens) 
       yield return p; 
     } 
    } 

    class State : IEnumerable<Person>, IEnumerable<City> 
    { 
     // State has cities: 
     City[] cities; 

     IEnumerator<Person> IEnumerable<Person>.GetEnumerator() 
     { 
      foreach (City c in cities) 
       foreach (Person p in c) 
        yield return p; 
     } 

     IEnumerator<City> IEnumerable<City>.GetEnumerator() 
     { 
      foreach (City c in cities) 
       yield return c; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      State s = new State(); 
      foreach (Person p in s) ; 
      foreach (City c in s) ; 
     } 
    } 
} 
+0

謝謝大家,我現在得到了我想知道的。 – 2012-08-08 20:17:11

回答

9

問題是IEnumerable<T>還需要您實施IEnumerable(非通用版本)。您需要實施GetEnumerator()調用。

這就是說,這將變得非常棘手,因爲你需要確定哪些東西要枚舉State。我個人而言,避免在同一個類實現IEnumerable<T>兩次,而不是返回枚舉的方法:

class State : IEnumerable<City> 
{ 
    public IEnumerable<Person> GetPeople() 
    { 
     // return people... 

在一般情況下,我認爲,試圖使事情是兩個不同的類型的枚舉是一個真正的設計缺陷。這將是更好的有國家實施更象:

public class State 
{ 
    public IEnumerable<City> Cities { get { // return cities... 

    public IEnumerable<People> People { get { // return people... 

這將要求您更改您的使用情況(略),更像:

foreach(Person person in theState.People) 
{ 
    // .... 

個人而言,我認爲這將是StateCity的更好方法。我寫這篇文章,如:

using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication1 
{ 

    class Person 
    { 
    } 

    class City 
    { 
     // City has citizens: 
     Person[] citizens; 

     public IEnumerable<Person> People 
     { 
      get 
      { 
       return citizens; 
      } 
     } 
    } 

    class State : IEnumerable<Person>, IEnumerable<City> 
    { 
     // State has cities: 
     City[] cities; 

     public IEnumerable<City> Cities 
     { 
      get 
      { 
       return cities; 
      } 
     } 

     public IEnumerable<Person> AllPeople 
     { 
      get 
      { 
       return Cities.SelectMany(c => c.People); 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      State s = new State(); 
      foreach (Person p in s.AllPeople) { /* Do something */ } 
      foreach (City c in s.Cities) { /* Do something */ } 
     } 
    } 
} 

我覺得這是很多更清晰 - 作爲一個城市人,但它本身不是,人物等

+0

+1的解決方法 – Sebastian 2012-08-08 20:07:28

+0

Darnit,在我發佈我的答案時,您更新了您的同樣的建議。 :P – MarkPflug 2012-08-08 20:11:59

2

您需要實現非通用變種,太! System.Collections.IEnumerable是沒有泛型類型參數的一個!

爲System.Collections.Generic.IEnumerable.GetEnumerator添加一個顯式接口實現 - 並使其拋出異常 - 您無法正確實現非通用接口。

+0

我應該如何實施它,因爲我想要返回所有人或所有城市 – 2012-08-08 20:06:32

+0

@NikolasJíša:請參閱Reed的解決方法 – Sebastian 2012-08-08 20:08:13

2

這實際上是一個有趣的問題,因爲裏德和塞巴斯蒂安都指出,你也需要實現非泛型方法。但是,您只能實現一次,並且您有兩個需要的接口。我認爲一個更好的設計可能沒有狀態實現IEnumerable,但有兩個屬性人民和城市,揭露IEnumerables。我認爲這也將是一個稍微更方便(可發現)的API。