C# 遍历基类和继承类的所有实例

C# 遍历基类和继承类的所有实例,c#,inheritance,polymorphism,draw,C#,Inheritance,Polymorphism,Draw,我有一个名为CollidableObject的基类和两个名为Player、敌军、InertoObject的继承类 我试图找到一种简单的方法来遍历它们的所有实例,因此我最初创建了一个类型为CollidableObject的列表,并将继承类的所有实例放在其中 问题是,由于多态性的本质,当我执行以下操作时 foreach (CollidableObject CollidableObject in collidableObjects) { if (CollidableObject is Player

我有一个名为
CollidableObject
的基类和两个名为
Player
敌军
InertoObject
的继承类

我试图找到一种简单的方法来遍历它们的所有实例,因此我最初创建了一个类型为
CollidableObject
的列表,并将继承类的所有实例放在其中

问题是,由于多态性的本质,当我执行以下操作时

foreach (CollidableObject CollidableObject in collidableObjects)
{
  if (CollidableObject is Player)
  {
    CollidableObject.Draw(spriteBatch, testPlayerTexture); 
  }
  // Then the same prodedure for each type of CollidableObject. 
  // Might change to switch or something.                              
}
它调用的draw方法是来自
collibableobject
base的通用draw方法,而不是来自Player/敌军/inertObject类的重写/新方法

我该怎么解决这个问题呢。有没有一种方法可以遍历来自同一棵树的对象集合,但保持它们的继承类型

您是否尝试过:

foreach (CollidableObject CollidableObject in collidableObjects)
{
    if (CollidableObject is Player)
    {
        ((Player) CollidableObject).Draw(spriteBatch, testPlayerTexture); 
    }    
    //Then the same prodedure for each type of CollidableObject. Might change to switch or something.                              
}

我会让每个类实现一个特定于该类的Draw方法。他们都需要相同的签名

那么您的foreach不关心它实际上是哪个类,并且看起来是这样的

foreach (CollidableObject CollidableObject in collidableObjects)
{
      CollidableObject.Draw(....);                                        
}
这将是“面向对象”的方法

是否没有办法遍历来自同一棵树的对象集合,但保持它们的继承类型

当然,有办法做到这一点。但是,您需要以适当的方式设置层次结构:

  • CollidableObject
    中的
    Draw
    方法需要标记为
    virtual
  • Player
    中的
    Draw
    方法需要标记为
    覆盖
这将确保来自post的调用将路由到
播放器
对方法的覆盖,而不是基本方法

另一方面,当您看到使用
is
操作符检查对象动态类型的代码时,如
if(CollidableObject是播放器)
中所述,您应该会强烈怀疑您的操作不正确。例如,您可能缺少一个


如果您只需要知道类型的正确纹理,可以将纹理放入
字典textureForType
,并使用可碰撞对象的
GetType()
在循环中拖动正确的纹理。

我意识到这是辅助的,但是,如果您必须为每个子类型提供不同的参数,这就有点违背了这一点。无论如何,看看这篇关于重写方法的文章;你应该有一个虚拟方法,并使用override关键字来覆盖它:“不是来自玩家/敌人/inertObject类的被覆盖/新方法。”-它是哪一个,被覆盖还是新的?这是OP已经在做的事情,但他们可能没有正确地使用虚拟/覆盖,如@dasblinkenLightThank的回答所述!关于“is”操作符,为什么在这种情况下它会出错?@user3120072虽然使用
is
不会自动出错,但它经常被用来代替更好的选择。例如,与其检查对象的动态类型,不如对其调用另一个提供纹理的虚拟方法。使用
if(x是TypeXyz)
调度链的危险在于,当您添加新类型时,您必须找到具有
if(x是…)
调度链的每个位置,并在那里为该新类型添加处理。在某些情况下,这只是大量的工作,但在其他情况下(当您编写库时),这是不可能的。这是可行的,但我会用这种方法丢失信息吗?@user3120072-不清楚您担心的是什么“信息”?如果您认为
(Player)
cast创建的新对象比您的假设是错误的-cast不会创建新对象,而是强制将对象引用为不同的类型(还将进行运行时检查以确保可以进行cast)。