【问题标题】:<list> of parent, do for each subclass<list> 的父类,为每个子类做
【发布时间】:2025-11-29 05:25:02
【问题描述】:

所以,我有一个 GameObject 类,我将它用作许多子类的基础。

class GameObject()
{
    blah;
}

class AmmoBox() : Gameobject()
{
    different blah;
}

class Taco() : GameObject() {very different blah;}

稍后我在列表中使用它们,我想为每个子类指定不同的更新/等行为。

foreach (AmmoBox a in GameObjects) { }

foreach (Taco t in GameObjects) { }

编译器抛出错误“无法将'GameObject'类型的对象转换为'AmmoBox'类型。我知道这是一个可悲的错误,我应该如何正确地做到这一点?

【问题讨论】:

    标签: c# vb.net list xna subclass


    【解决方案1】:

    您可以使用OfType根据类型进行过滤:

    foreach (AmmoBox a in GameObjects.OfType<AmmoBox>()) { }
    

    【讨论】:

      【解决方案2】:

      您不能直接将它们转换为foreach(..),请尝试循环它们并检查它们是否属于您想要的类型。使用as 操作符检查这一点,如果它属于该类型,它将返回被转换的对象,否则返回null。

      foreach (GameObject object in GameObjects)
      {
           AmmoBox a = object as AmmoBox;
           if (a != null)
           {
               //Do something with a
           }
      
           Taco t = object as Taco;
           if (taco != null)
           {
               //Do something with t
           }
      }
      

      您也可以使用 LINQ 的 OfType 扩展来根据它们的类型来选择它们。

      foreach (AmmoBox a in GameObjects.OfType<AmmoBox>())
      {
           //Do something with a
      }
      foreach (Taco t in GameObjects.OfType<Taco>())
      {
           //Do something with a
      }
      

      【讨论】:

      • 这两种方法会更好地适用于 100 种左右的类型吗?非常感谢!
      • 唯一的方法就是自己测试它们,尽管 100 种类型对任何一种都不太难处理。
      • 再次感谢,这个社区的新手,有什么方法可以 +1 吗?有什么我能做的吗?
      • 只是一个问题,“OfType”解决方案不会比“as”运算符使用更多资源吗?
      • 我想是的,我稍后再查
      【解决方案3】:

      GameObjects 变量包含不同类型的游戏对象。因此,当您尝试强制转换为不匹配的类型时,它会引发错误。

      一种方法是在迭代时过滤集合。这涉及检查对象的实际类型。这在简单的情况下是可以的,但并不是真正被认为是“好”的代码,因为它违背了使用接口的目的。

      相反,尝试在每个游戏对象中创建一个Update 方法。像这样:

      abstract class GameObject
      {
          ...
          public abstract void Update();
      }
      
      class Ammo : GameObject
      {
          public override void Update()
          {
              // Stuff to update Ammo
          }
      }
      

      对您的其他游戏对象执行类似操作。然后在你的 foreach 循环中,对每个对象调用这个方法。

      foreach (GameObject g in GameObjects)
      {
          g.Update();
      }
      

      这很好,很干净。它还将特定的细节抽象到特定的类中。这是一种众所周知的设计模式,称为Strategy Pattern

      【讨论】:

        最近更新 更多