在列表中查找子类

时间:2011-03-21 12:37:40

标签: c# list xna

嗨,我现在遇到了一些问题,我目前有一个班级“船”,其子类为“播放器”& “敌人”他们都在名单“船”中

我要做的是从“船舶”列表中提取“Player thePlayer” 我已经尝试过使用List.Find()而没有任何成功,是不是我使用它错了或是处理这个问题的错误方法?

    for (int i = 0; i < HomingBullets.Count; i++)
    {
        HomingBullet h = HomingBullets.ElementAt(i);
        Player thePlayer = ??? List.Find ???
        h.Update(gameTime, thePlayer.position);
    }

h.Update接受两个参数(gameTime&amp; Vector2) 我正在尝试使用上面的代码提取Vector2。

请记住,自今年年初以来我只使用过C#,尽管我有多年的各种语言编程经验。

5 个答案:

答案 0 :(得分:3)

您可以使用LINQ的OfType<>运算符仅从列表或IEnumerable中返回特定类型的对象。例如。你可以写

Ships.OfType<Player>()

仅返回Player类型的实例。

这是一种非常低效的搜索方式,因为它遍历所有Ships。我怀疑玩家船只只占总船只的很小一部分。最好保留一个引用Ship集合中的Ship实例的Player船的单独列表。

答案 1 :(得分:1)

list.Find(sh => sh is Player);

这相当于创建一个方法:

bool IsPlayer(Ship sh)
{
  return sh is Player;
}

然后迭代直到该方法在每个项目上调用时返回true(如果没有找到这样的项目,则返回null。

答案 2 :(得分:1)

您可以使用is关键字测试对象是否是给定类的实例:x is Player对于您的播放器对象应为true,对于Enemy的实例为false列表。

isPlayer课程中定义Ship方法(PlayerEnemy中的定义返回不同的值)可能是更好的方式,或者 - 如果在事实上,总有一个Player对象 - 将其保存在其他地方,而不是在列表中反复查找。

答案 3 :(得分:1)

可以说,比任何一个更好的解决方案是使用GameComponent(或DrawableGameComponent)和GameServices。这将允许您能够抓取Player对象,而无需始终对其进行硬性引用。相反,您只需要引用Game对象。

其他参考

答案 4 :(得分:0)

最简单的解决方案是向Ship类添加readonly属性:

class Ship
{
    public abstract bool IsPlayer { get; }
}

class Player : Ship
{
    public override bool IsPlayer { get { return true; } }
}

class Enemy : Ship
{
    public override bool IsPlayer { get { return false; } }
}

然后你可以做

var thePlayer = (Player)shipList.Find(s => s.IsPlayer);

如果你可以将该对象用作一般Player而不是更具体的Ship,我可能会转向Player(我假设shipList是一个List<Ship>,对吗?)。

其他解决方案(例如使用is关键字或等效的LINQ shipList.OfType<Player>().Single()也可以正常工作,但检查运行时类型将比IsPlayer属性检查慢得多