【问题标题】:C# implementing generic IEnumerableC# 实现通用 IEnumerable
【发布时间】:2012-08-08 20:02:14
【问题描述】:

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

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

【问题讨论】:

  • 谢谢大家,我现在想知道什么了。

标签: c# generics interface ienumerable


【解决方案1】:

问题是IEnumerable&lt;T&gt; 还需要你实现IEnumerable(非通用版本)。您需要实现两个GetEnumerator() 调用。

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

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)
{
    // ....

就个人而言,我认为这对于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 */ } 
        }
    }
}

我发现这更清楚 - 作为一个城市人,但它本身不是人,等等。

【讨论】:

  • Darnit,在我发布我的答案时,你用同样的建议更新了你的答案。 :P
【解决方案2】:

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

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

【讨论】:

  • 我应该如何实现它,因为我想返回所有的人或所有的城市
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多