C#实现通用的IEnumerable

Nik*_*íša 2 c# generics ienumerable interface

我一直在想是否有可能说出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) ;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ree*_*sey 9

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

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

class State : IEnumerable<City>
{
    public IEnumerable<Person> GetPeople()
    {
      // return people...
Run Code Online (Sandbox Code Playgroud)

一般来说,我认为尝试使某些东西成为两种不同类型的枚举实际上是一个设计缺陷.最好让国家得到更好的实施:

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

    public IEnumerable<People> People { get { // return people...
Run Code Online (Sandbox Code Playgroud)

这将要求您(略微)更改您的使用情况,更像是:

foreach(Person person in theState.People)
{
    // ....
Run Code Online (Sandbox Code Playgroud)

就个人而言,我认为这将是两个更好的方法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 */ } 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我觉得这是很多更清晰-作为一个城市都有人,但它本身不是,人物等