2016-06-13 149 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。