C#实现泛型IEnumerable

C#实现泛型IEnumerable

问题描述:

我一直想知道是否可以说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

问题是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

您需要实现非通用变种,太! 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

这实际上是一个有趣的问题,因为里德和塞巴斯蒂安都指出,你也需要实现非泛型方法。但是,您只能实现一次,并且您有两个需要的接口。我认为一个更好的设计可能没有状态实现IEnumerable,但有两个属性人民和城市,揭露IEnumerables。我认为这也将是一个稍微更方便(可发现)的API。