Найти подкласс в списке - PullRequest
1 голос
/ 21 марта 2011

Привет, я в данный момент в некоторой проблеме, у меня в настоящее время есть класс "Корабль" с подклассами "Игрок" и "Враг", оба они находятся в списке "Корабли"

Что яя пытаюсь сделать, это извлечь "Player thePlayer" из списка "Ships", я пытался использовать 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 & Vector2) Я пытаюсь извлечь Vector2, используя приведенный выше код.

Имейте в виду, у меня толькоЯ использую C # с начала этого года, хотя у меня есть несколько лет опыта программирования на разных языках.

Ответы [ 5 ]

3 голосов
/ 21 марта 2011

Вы можете использовать оператор LINQ OfType <> , чтобы возвращать только объекты определенного типа из списка или IEnumerable в целом.Например, вы можете написать

Ships.OfType<Player>()

, чтобы вернуть только экземпляры типа Player.

Это очень неэффективный способ поиска, поскольку он повторяется на всех кораблях.Я подозреваю, что корабли игроков составляют очень маленький процент от общего количества кораблей.Было бы лучше вести отдельный список кораблей игрока, который ссылается на экземпляры кораблей в коллекции кораблей.

1 голос
/ 22 марта 2011

Возможно, гораздо лучшим решением, чем любое другое, является использование GameComponent (или DrawableGameComponent) и GameServices.Это позволит вам иметь возможность захватить объект Player, не обращаясь к нему постоянно.Вместо этого вам нужна только ссылка на объект Game.

Другие ссылки

1 голос
/ 21 марта 2011

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

Это эквивалентно созданию метода, подобного:

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

И затем итерация до тех пор, пока этот метод не вернет true при вызове для каждого элемента (или ноль, если такой элемент не найден.

1 голос
/ 21 марта 2011

Вы можете проверить, является ли объект экземпляром данного класса, используя ключевое слово is: x is Player будет истинным для вашего объекта игрока и ложным для экземпляров Enemy в списке.

Возможно, будет лучше определить метод isPlayer для вашего класса Ship (с определениями в Player и Enemy, возвращающими разные значения), или - если на самом деле всегда есть только один Player объект - держать его где-то в другом месте, а не многократно искать его в вашем списке.

0 голосов
/ 21 марта 2011

Самое простое решение было бы добавить свойство readonly к классу Ship:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...