2016-06-13 198 views
0

我有我想要在下面做的简化版本。我有一个由SolarSystem类使用的类Planet。我想使用foreach循环为SolarSystem中的每个Planet编写orbitTimeInDays。C#枚举对象foreach

错误CS1579 foreach语句不能 型“TestEnum.SolarSystem”的变量操作,因为“TestEnum.SolarSystem”不包含 一个公共定义“的GetEnumerator”

问题是枚举,我已经阅读了几篇有关使对象成为Enumerable的文章和问题,但我似乎无法解决如何将它应用于SolarSystem,以便检查它构建的每个Planet。 (最终还会包含小行星等等,所以它不仅仅是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... 
    } 
} 
+2

问题是你的行星是同一类的每一个单独的属性,你可以做到这一点,使用一些幻想,但realisitcally,你会更好地与你的solarsystem中的行星列表..也许一些其他的道具,那么你可以foreach的行星列表.. – BugFinder

+0

一个'ForEach'循环对阵列等工作,类似的方式为'for'循环。你有一个类而不是几个属性。 –

回答

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

+0

非常感谢,这正是我所需要的。 – FridgeMagnet

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

你不能只是列举的所有属性。也许最好的解决办法是给SolarSystem List或行星的词典,所以你可能会得到这样的:

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的属性。即使你需要找到一颗行星,找到它的简单循环也很好。毕竟,在太阳系中你不会有成千上万的行星,所以对Dictionary的搜索机制没有太大的需求。

List的一个优点是它保留了添加元素的顺序。 Dictonary不会,但如果您需要这两个功能,还有OrderedDictionary。

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

+1

如果您只打算使用这些值,为什么要使用字典?那么为什么不使用'List '呢? –

+0

你也可以使用一个列表(我在文中建议)。这取决于用途。 Dictionary允许你在其他场景中按名称查找行星。 Linq也可以做到这一点,但字典更快。 – GolezTrol

+0

然后解释说,在你的答案请:) –

0

您正在为每个星球创建对象。 foreach将只在收集上工作。 Better create List planetList = new List();

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