Search code examples
c#foreachenumerationenumerate

C# Enumerating Object foreach


I have a simplified version of what I want to do below. I have a class Planet which is used by the class SolarSystem. I want to use a foreach loop to write the orbitTimeInDays for each Planet in SolarSystem.

Error CS1579 foreach statement cannot operate on variables of type 'TestEnum.SolarSystem' because 'TestEnum.SolarSystem' does not contain a public definition for 'GetEnumerator'

The problem is enumeration, I've read several articles and questions about making objects Enumerable, but I can't seem to work out how to apply it to SolarSystem so I can check each Planet it's constructed from. (Eventually it will contain asteroids, etc as well, so it's not just 8 planets and Pluto.)

Can someone please help me make sense of how to Enumerate SolarSystem.

class Program
{
    static void Main(string[] args)
    {
        SolarSystem solarSystem = new SolarSystem();
        solarSystem.mercury.orbitTimeInDays = 88;
        solarSystem.venus.orbitTimeInDays = 225;
        // etc...

        foreach (Planet planet in solarSystem)
        {
            Console.WriteLine("Time taken to orbit sun (in days) : " + planet.orbitTimeInDays.ToString());
        }
    }
}

public class Planet 
{
    public double distanceFromEarth { get; set; }
    public int orbitTimeInDays { get; set; }
    // etc...

    public Planet() { }
}

public class SolarSystem 
{ 
    public Planet mercury { get; set; }
    public Planet venus { get; set; }
    // etc...

    public SolarSystem()
    {
        mercury = new Planet();
        venus = new Planet();
        // etc...
    }
}

Solution

  • Your solar system doesn't tell it can iterate over anything. You have to implement IEnumerable to tell the compiler that:

    public class SolarSystem : IEnumerable<Planet>
    {
        public IEnumerator<Planet> GetEnumerator()
        {
            yield return mercury;
            yield return venus;
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    

    This is a basic implementation of an enumerable. It uses the yield keyword to generate an enumerator for you on the fly.

    Optionally, you could create a property Planets in your class, probably something like this:

    List<Planet> Planets {get;} = List<Planet>();
    

    Then you can iterate over solarSystem.Planets.