C#枚举对象foreach

时间:2016-06-13 12:41:53

标签: c# foreach enumeration enumerate

我有一个简化版本,我想在下面做。我有一个由SolarSystem类使用的星球。我想使用foreach循环为SolarSystem中的每个Planet编写orbitTimeInDays。

  

错误CS1579 foreach语句无法对类型变量进行操作   'TestEnum.SolarSystem'因为'TestEnum.SolarSystem'不包含   'GetEnumerator'的公共定义

问题是枚举,我已经阅读了几篇关于使对象可枚举的文章和问题,但我似乎无法弄清楚如何将它应用于SolarSystem,因此我可以检查它构造的每个星球。 (最终它也将包含小行星等,所以它不仅仅是8个行星和冥王星。)

有人可以帮我理解如何枚举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...
    }
}

4 个答案:

答案 0 :(得分:5)

你的太阳系并没有告诉它可以迭代任何东西。您必须实现IEnumerable以告诉编译器:

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

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

这是可枚举的基本实现。它使用yield关键字为您即时生成枚举器。

或者,您可以在班级中创建一个属性Planets,可能是这样的:

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

然后你可以迭代solarSystem.Planets

答案 1 :(得分:2)

您不能只枚举所有属性。也许最好的解决方案是给SolarSystem一个列表或行星词典,所以你可以得到这样的东西:

public class SolarSystem 
{ 
    public Dictionary<string, Planet> Planets { get; } = new Dictionary<string, Planet>();

    public SolarSystem()
    {
        Planets.add('Mercury', new Planet());
        Planets.add('Venus', new Planet());
        // etc...
    }
}

然后列举如下:

foreach (Planet planet in solarSystem.Planets.Values)

字典允许您按名称快速查找行星,但如果您不需要,则可以使用List,它只包含没有名称作为键的值(行星)。你可以改名为Planet的一个属性。即使你需要找到一个行星,一个简单的循环来找到它也是好的。毕竟,你不会在太阳系中拥有成千上万的行星,所以不需要大词典更快的搜索机制。

List的一个优点是它保留了添加元素的顺序。 Dictonary没有,虽然还有OrderedDictionary,以防你需要这两个功能。

无论如何,使用这样一个最适合您需求的集合类,可以让您不必自己实现GetEnumerator(来自IEnumerable接口)。

答案 2 :(得分:0)

这不可能像你这样做。您可以创建一个行星列表/数组,而不是为行星创建弹性属性。这样您就可以从solorsystem外部创建新的行星。 ; - )

类似的东西:

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

    public Planet() { }
}

public class SolarSystem 
{ 
    public List<Planet> planets {get; private set;}

    public SolarSystem()
    {
        planets = new List<Planet>();
        planets.Add( new Planet { name = "mercury", distanceFromEarth = 23456 });
        planets.Add( new Planet { name = "venus", distanceFromEarth = 12456 });
    }
}

static void Main(string[] args)
{
    SolarSystem solarSystem = new SolarSystem();

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

答案 3 :(得分:0)

您正在为每个星球创建对象。 foreach仅适用于收藏。 更好地创造 列出planetList = new List();

并将行星添加到planetList并应用foreach。