C# - Foreach循环仅迭代某些对象

时间:2017-11-20 20:07:44

标签: c# arrays object foreach

我正在学习编程,我不得不创建一个蛇游戏。

在游戏中,蛇有大约5种可能的消耗品,我决定将每个新的Consumable放在Consumable阵列中。

现在我想在数组中使用foreach循环进行迭代,并执行以下操作:

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

但是当数组中有不同的对象,如AppleSegmentRemover时(这是可能的,因为它们继承自Consumable类),编译器会迭代SegmentRemover也是如此,我收到了无效的强制转换异常。

我想,因为我在foreach循环中声明我只想迭代Apple个对象,它应该可以工作。

有没有简单的方法来解决这个问题?最好不要使用vartypeof之类的内容,因为我还不允许使用这些内容。

3 个答案:

答案 0 :(得分:5)

您真正想要的只是那些“可投递”到Apple类型的项目。对于该用途OfType<Apple>(使用linq):

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

非linq解决方案几乎可以使用as operator

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

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

答案 1 :(得分:4)

你可以翻转逻辑,让每个耗材在渲染器中绘制自己:

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

这样,您在Draw的每个实例上以多态方式调用IConsumable,因此执行的代码在运行时由实现IConsumable接口的实际类决定。

答案 2 :(得分:-2)

您的耗材是集合,您是否尝试使用存储集合的对象实例访问集合?如是: 尝试:

HdfsClient