2

我一直在想是否有可能让说State类实施IEnumerable<Person>IEnumerable<City>所以我可以通过 foreach 以及所有城市让所有居住在该州的人。它甚至不会编译这样说:(Error 1 'ConsoleApplication1.City' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'奇怪)......这是代码:

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) ;
        }
    }
}
4

3 回答 3

10

问题是这IEnumerable<T>还需要您实现IEnumerable(非通用版本)。您需要实现这两个GetEnumerator()调用。

话虽如此,这将变得非常棘手,因为您的State班级将需要确定要枚举的内容。我个人会避免IEnumerable<T>在一个类中实现两次,而是将可枚举作为方法返回:

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

总的来说,我认为试图使某物成为两种不同类型的枚举确实是一个设计缺陷。最好让 State 更像:

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

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

这将要求您(稍微)更改您的用法,更像是:

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

就个人而言,我认为这对State和都是更好的方法City。我会这样写:

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 */ } 
        }
    }
}

我发现这一点要清楚得多——因为一个城市有人,但它本身不是人,等等。

于 2012-08-08T20:05:21.157 回答
2

您还需要实现非泛型变体!System.Collections.IEnumerable 是没有泛型类型参数的那个!

为 System.Collections.Generic.IEnumerable.GetEnumerator 添加一个显式接口实现 - 并使其引发异常 - 您无法正确实现非泛型接口。

于 2012-08-08T20:05:06.437 回答
2

这实际上是一个有趣的问题,因为 Reed 和 Sebastian 都指出,您还需要实现非泛型方法。但是,您只能实现一次,并且需要两个接口。我认为更好的设计可能根本没有状态实现 IEnumerable,但有两个属性 People 和 Cities 公开 IEnumerables。我认为这也是一个更方便(可发现)的 API。

于 2012-08-08T20:11:01.760 回答