C# 枚举对象 foreach
C# Enumerating Object foreach
我在下面有一个我想做的简化版本。我有一个 class 行星供 class 太阳系使用。我想使用 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'
问题是枚举,我已经阅读了几篇关于使对象可枚举的文章和问题,但我似乎无法弄清楚如何将它应用到 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...
}
}
你的太阳系并没有告诉它可以迭代任何东西。你必须实现 IEnumerable
来告诉编译器:
public class SolarSystem : IEnumerable<Planet>
{
public IEnumerator<Planet> GetEnumerator()
{
yield return mercury;
yield return venus;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
这是可枚举的基本实现。它使用 yield
关键字为您即时生成一个枚举器。
您可以选择在您的 class 中创建一个 属性 Planets
,大概是这样的:
List<Planet> Planets {get;} = List<Planet>();
然后你可以遍历 solarSystem.Planets
.
这不可能像您这样做的方式。您可以创建 list/array 个行星,而不是为行星创建单个属性。这样你就可以从太阳系外创造新的行星。 ;-)
类似于:
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());
}
}
您不能只枚举所有属性。也许最好的解决方案是给 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)
字典可让您通过名称快速查找行星,但如果不需要,您可以改用列表,它只包含值(行星),没有名称作为键。您可以改为将名称设为 Planet 的 属性。即使你需要找到一颗行星,一个简单的循环来找到它也是好的。毕竟,你不会在太阳系中拥有成千上万的行星,所以对字典的快速搜索机制没有太大的需求。
List 的一个优点是它保留了您添加元素的顺序。 Dictonary 没有,尽管也有 OrderedDictionary 以备不时之需。
无论如何,使用这样一个集合 class,无论哪个最适合您的需要,您都不必自己实现 GetEnumerator(从 IEnumerable 接口)。
您正在为每个行星创建对象。
foreach 仅适用于集合。
更好地创造
列出 planetList = new List();
并将行星添加到 planetList 并申请每个。
我在下面有一个我想做的简化版本。我有一个 class 行星供 class 太阳系使用。我想使用 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'
问题是枚举,我已经阅读了几篇关于使对象可枚举的文章和问题,但我似乎无法弄清楚如何将它应用到 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...
}
}
你的太阳系并没有告诉它可以迭代任何东西。你必须实现 IEnumerable
来告诉编译器:
public class SolarSystem : IEnumerable<Planet>
{
public IEnumerator<Planet> GetEnumerator()
{
yield return mercury;
yield return venus;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
这是可枚举的基本实现。它使用 yield
关键字为您即时生成一个枚举器。
您可以选择在您的 class 中创建一个 属性 Planets
,大概是这样的:
List<Planet> Planets {get;} = List<Planet>();
然后你可以遍历 solarSystem.Planets
.
这不可能像您这样做的方式。您可以创建 list/array 个行星,而不是为行星创建单个属性。这样你就可以从太阳系外创造新的行星。 ;-)
类似于:
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());
}
}
您不能只枚举所有属性。也许最好的解决方案是给 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)
字典可让您通过名称快速查找行星,但如果不需要,您可以改用列表,它只包含值(行星),没有名称作为键。您可以改为将名称设为 Planet 的 属性。即使你需要找到一颗行星,一个简单的循环来找到它也是好的。毕竟,你不会在太阳系中拥有成千上万的行星,所以对字典的快速搜索机制没有太大的需求。
List 的一个优点是它保留了您添加元素的顺序。 Dictonary 没有,尽管也有 OrderedDictionary 以备不时之需。
无论如何,使用这样一个集合 class,无论哪个最适合您的需要,您都不必自己实现 GetEnumerator(从 IEnumerable 接口)。
您正在为每个行星创建对象。 foreach 仅适用于集合。 更好地创造 列出 planetList = new List();
并将行星添加到 planetList 并申请每个。