C# - 只对特定对象进行迭代的 Foreach 循环

3

我正在学习编程,我需要创建一个贪吃蛇游戏。

在游戏中,有大约5个可能的物品可以被蛇吃掉,因此我决定将每个新的可消耗品(Consumable)放入一个可消耗品(Consumable)数组中。

现在我想通过foreach循环遍历数组并执行以下操作:

foreach (Apple apple in consumables)
{
    renderer.DrawApple(apple);
}

然而,当数组中有不同的对象时,例如一个Apple和一个SegmentRemover(这是可能的,因为它们都继承自Consumable类),编译器也会迭代SegmentRemover,然后我就会得到一个无效的转换异常。
我认为既然我在foreach循环中声明只想迭代Apple对象,那么它应该能够工作。
有什么简单的方法来解决这个问题吗?最好不要使用像vartypeof这样的东西,因为我还没有被允许使用它们。

1
“Consumables” 的定义是什么?“消耗品”、“Apple” 和 “SegmentRemover” 之间的关系是什么? - Gilad Green
1
FYI,var对你完全没有帮助。consumables的类型是什么?你可以使用LINQ来过滤列表吗?如果你能发布AppleSegmentRemoverConsumable的定义,那将非常有帮助。 - maccettura
Apple和SegmentRemover是具有起源的类,它们继承自Consumable类。另外,我也不允许使用linq。 - Patai
1
当我开始使用C#工作时,我也有同样的误解;尽管现在我明白了为什么会这样,但它总是让我感到奇怪,因为它引入了一个强制转换。建议使用 OfType<Apple> 序列运算符的答案是个好主意。 - Eric Lippert
@Patai - 以下的解决方案有没有帮助你解决问题? - Gilad Green
3个回答

5
您真正想要的只是那些可转换为“Apple”类型的项。为此,请使用OfType<Apple> (使用linq):
foreach (Apple apple in consumables.OfType<Apple>())
{
    renderer.DrawApple(apple);
}

一种非Linq解决方案是使用as运算符,它可以做类似的事情:

foreach(var item in consumbles)
{
    var apple = item as Apple;
    if(apple != null) 
    {
        renderer.DrawApple(apple);
    }
}

然而,在我的看法中,如果所有这些项目都放在同一个列表中,并且它们已经从Consumble继承,更好的设计是使用多态性为每种类型的Consumable定义一个draw方法,如@dasblinkenlight所建议的那样。并为每个类型具有特定的实现。对于SegmentRemover这种情况,它可能是一个空实现,在Apple中,它可能会调用renderer


3
您可以翻转逻辑,让每个可消耗品在渲染器中自行绘制:
interface IConsumable {
    void draw(Renderer renderer);
}
class Apple : IConsumable {
    void draw(Renderer renderer) {
        renderer.DrawApple(this);
    }
}
class SegmentRemover : IConsumable {
    void draw(Renderer renderer) {
        renderer.DrawSegmentRemover(this);
    }
}

现在你的循环可以像这样进行:
foreach (IConsumable consumable in consumables) {
    consumable.Draw(renderer);
}

这样你就可以对每个IConsumable的实例进行多态调用Draw,因此执行的代码是由实现IConsumable接口的实际类在运行时决定的。


我刚学习了接口,不过我会尝试这样实现。谢谢! - Patai

-2

你的消耗品是一个集合,你是否试图使用存储集合的对象实例来访问集合?如果是: 请尝试:

foreach (Apple apple in consumables.consumables)
{
    renderer.DrawApple(apple);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接