I have been wondering if it is possible to make say State class implementing IEnumerable<Person> and IEnumerable<City> so I could get all the people living in the state via foreach as well as all the cities. It won’t even compile saying this: Error 1 'ConsoleApplication1.City' does not implement interface member 'System.Collections.IEnumerable.GetEnumerator()'(weird)… Here is the code:
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) ;
}
}
}
The problem is that
IEnumerable<T>also requires you to implementIEnumerable(the non generic version). You need to implement bothGetEnumerator()calls.That being said, this will get very tricky, as you’re
Stateclass will need to determine which thing to enumerate. I would, personally, avoid implementingIEnumerable<T>twice in one class, and instead return the enumerable as a method:In general, I think that trying to make something be an enumeration of two separate types is really a design flaw. It would be better to have State be implemented more like:
This would require you to change your usage (slightly), to be more like:
Personally, I think this would be a better approach for both
StateandCity. I would write this like:I find this is much more clear – as a City has People, but it is not, itself, People, etc.