简体   繁体   English

C#枚举对象foreach

[英]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. 我有一个类,该类由SolarSystem类使用。 I want to use a foreach loop to write the orbitTimeInDays for each Planet in SolarSystem. 我想使用一个foreach循环为SolarSystem中的每个星球编写orbitTimeInDays。

Error CS1579 foreach statement cannot operate on variables of type 'TestEnum.SolarSystem' because 'TestEnum.SolarSystem' does not contain a public definition for 'GetEnumerator' 错误CS1579 foreach语句无法对类型为“ TestEnum.SolarSystem”的变量进行操作,因为“ TestEnum.SolarSystem”不包含“ 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. 问题是枚举,我已经阅读了几篇有关使对象成为可枚举对象的文章和问题,但我似乎无法弄清楚如何将其应用于SolarSystem,因此我可以检查其构造的每个行星。 (Eventually it will contain asteroids, etc as well, so it's not just 8 planets and Pluto.) (最终它还将包含小行星等,因此它不仅是8个行星和冥王星。)

Can someone please help me make sense of how to Enumerate SolarSystem. 有人可以帮我弄清楚如何枚举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...
    }
}

Your solar system doesn't tell it can iterate over anything. 您的太阳系不会告诉它可以迭代任何事物。 You have to implement IEnumerable to tell the compiler that: 您必须实现IEnumerable才能告诉编译器:

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. 它使用yield关键字为您动态生成一个枚举器。

Optionally, you could create a property Planets in your class, probably something like this: (可选)您可以在类中创建属性Planets ,可能是这样的:

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

Then you can iterate over solarSystem.Planets . 然后,您可以遍历solarSystem.Planets

You cannot just enumerate all properties. 您不能只列举所有属性。 Maybe the best solution would be to give SolarSystem a List or a Dictionary of planets, so you could get something like this: 也许最好的解决方案是为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...
    }
}

And then enumerate like this: 然后像这样枚举:

foreach (Planet planet in solarSystem.Planets.Values)

A dictionary allows you to quickly find a planet by name, but if you don't require that, you could use a List instead, which just contains the values (the planets) without the name as a key. 词典允许您快速按名称查找行星,但是如果不需要,可以使用列表,该列表仅包含值(行星)而不用名称作为关键字。 You could make the name a property of Planet instead. 您可以将名称设为Planet的属性。 And even if you would need to find a planet, a simple loop to find it is also good. 即使您需要找到一个行星,一个简单的循环来找到它也是很好的。 After all, you're not going to have thousands of planets in the solar system, so there is no big need for Dictionary's faster searching mechanism. 毕竟,您不会在太阳系中拥有成千上万个行星,因此对Dictionary的更快搜索机制没有太大的需求。

An advantage of a List is that it retains the order in which you add the elements. 列表的一个优点是它保留了添加元素的顺序。 Dictonary doesn't, although there is also OrderedDictionary in case you would need both features. Dictonary不需要,尽管也有OrderedDictionary,以防您需要两个功能。

Anyway, using such a collection class, whichever best fits your needs, saves you from having to implement the GetEnumerator (from the IEnumerable interface) yourself. 无论如何,使用最适合您需求的此类收集类可以使您不必自己实现GetEnumerator(通过IEnumerable接口)。

This is not possible like the way you are doing it. 这不可能像您所做的那样。 Instead of creating induvidual properties for planets, you could create a list/array of planets. 您可以创建行星的列表/数组,而不是为行星创建独立的属性。 This way you are able to create new planets from outside the solorsystem. 这样,您就可以从系统外部创建新的行星。 ;-) ;-)

Something like: 就像是:

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

You are creating objects for each planet. 您正在为每个星球创建对象。 foreach will work only on collection. foreach仅适用于集合。 Better create List planetList = new List(); 更好地创建List planetList = new List();

and add planets it to planetList and apply foreach. 并将其添加到planetList并申请foreach。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM