【问题标题】:C# Enumerating Object foreachC# 枚举对象 foreach
【发布时间】:2016-06-13 12:41:53
【问题描述】:

我在下面有一个我想要做的简化版本。我有一个由 SolarSystem 类使用的 Planet 类。我想使用 foreach 循环为 SolarSystem 中的每个行星编写 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...
    }
}

【问题讨论】:

  • 问题是你的行星是同一类的每个单独的属性,你可以用一点花哨的方式来做到这一点,但实际上,你最好用你的太阳系中的行星列表来做。也许其他一些道具,然后你可以foreach行星列表..
  • ForEach 循环适用于数组等,其方式类似于for 循环。你有一个类而不是几个属性。

标签: c# foreach enumeration enumerate


【解决方案1】:

你的太阳系并没有告诉它可以迭代任何东西。你必须实现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

【讨论】:

  • 非常感谢,这正是我所需要的。
【解决方案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 的属性。即使你需要找到一颗行星,一个简单的循环来找到它也很好。毕竟,太阳系中不会有成千上万的行星,因此不需要 Dictionary 更快的搜索机制。

List 的一个优点是它保留了添加元素的顺序。字典没有,但也有 OrderedDictionary 以防您需要这两个功能。

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

【讨论】:

  • 如果您只打算使用值,为什么还要使用字典?那为什么不使用List&lt;Planet&gt;呢?
  • 您也可以使用列表(我在文本中建议)。这取决于用途。字典允许您在其他场景中按名称查找行星。 Linq 也可以做到这一点,但字典更快。
  • 那么请在你的回答中解释一下:)
  • 我做到了。你喜欢它? :)
【解决方案3】:

这是不可能的,就像你正在做的那样。您可以创建行星列表/数组,而不是为行星创建单独的属性。这样你就可以从太阳系之外创造新的行星。 ;-)

类似:

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2012-08-12
      • 2011-04-24
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多