Являются ли методы расширения решением этой проблемы? - PullRequest
3 голосов
/ 14 августа 2011

В моей программе исходный прямоугольник для рисования может быть либо обычным прямоугольником, пустым прямоугольником, либо прямоугольником с X или Y, равным -1. Если прямоугольник нормальный (например, (0, 0, 64, 64)), то он просто рисует это из текстуры. Если это Rectangle.Empty, то он ничего не рисует и просто продолжает цикл. Если исходный прямоугольник имеет X или Y, равный -1, то определяется, что он является плиткой столкновения.

Проблема в том, что -1 не является интуитивно понятным. Это сбивает с толку и плохое решение. Кроме того, если появится больше типов плиток, они начнут смешиваться, например, -2 означает медленную плитку или -3, означающую водную плитку.

Другая проблема заключается в том, что, поскольку я не знал, что на ранних этапах будут собираться фрагменты столкновений, и с правильными прямоугольниками XNA все в порядке, вся система (к счастью, только около 1000 строк кода на данный момент) использует прямоугольники XNA. Я полагаю, что на этом этапе мне придется создать отдельный класс и обновить все, но я не уверен.

Что было бы хорошим решением для этого? Я не особо баловался методами расширения. Могут ли они быть применены к классу Rectangle и получить такие методы, как IsCollisionTile () или IsBlankTile ()? Первоначально я надеялся, что смогу извлечь из класса Rectangle класс Tile, но, к сожалению, класс запечатан. Я полагаю, что еще одним простым решением может быть создание класса глобальных констант, где -1 - это CollisionTile, 0 - это BlankTile и так далее. Это, по крайней мере, сделало бы это немного более понятным, но мне все равно это кажется уродливым:

if (tiles[y, x].X == Constants.BlankTile)
    continue;

if (tiles[y, x].X == Constants.CollisionTile)
{
    Utility.DrawRectangle(spriteBatch, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), collisionTileColor);
    continue;
}

spriteBatch.Draw(tileset, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), tiles[y, x], Color.White);

Если бы только было свойство, я мог бы использовать как Tag с элементами управления. Я действительно хотел бы не отказываться от использования класса Rectangle, потому что он настолько встроен в систему, и программа является чисто функциональной, просто не эстетичной в этом отношении. В идеале я бы предпочел решение, которое просто позволяет расширить класс Rectangle, чтобы каким-то образом иметь возможность общаться со своими клиентами, каким типом плитки это должно быть.

Ну, тогда это заняло гораздо больше времени, чем я ожидал. Извините за долгое чтение x_x

Ответы [ 3 ]

2 голосов
/ 14 августа 2011

Я бы порекомендовал установить глобальные константы. Проблема с методами расширения в этом случае возникает потому, что Rectangle - это структура, тип значения. Это означает, что ваш метод расширения работает с копией прямоугольника, а не с оригиналом.

1 голос
/ 14 августа 2011

Если класс не может быть унаследован от (что обычно является подходящим решением здесь. Позор вам, Microsoft!), Тогда методы расширения могут демонстративно работать, как вы описали. Проблема в том, что - IMO, в C # и в ООП вообще не так удобно использовать методы, которые работают как геттеры. Вот для чего нужны добытчики. Поэтому я думаю, что опция глобальных констант больше соответствует общему стилю, но это только мое мнение.

Из полностью программируемого POV - оба метода действительны, когда класс глобальной константы может быть немного быстрее (хотя я не уверен в этом)

0 голосов
/ 14 августа 2011

В начале вы должны подумать, когда вы используете свои методы

IsCollisionTile() and IsBlankTile()

У вас есть два варианта:
*) Вы хотите использовать его глобально, тогда вам лучше написать Utility-Class, чтобы ваши методы были там, где они вам нужны:

public static class CollisionHelper
{
  public static Boolean IsCollisionTile(ITile tileToCheck) 
  {
    ...
  }
}

*) Во-вторых, если вы хотите использовать его только в связи с вашими плитками, вы должны обязательно написать метод расширения, например, принять каждый ITile-объект. Методы расширений - отличный способ расширить возможности классов. Образец может быть:

public class RectangleTile : ITile
{
  public static Boolean IsCollisionTile(this ITile tileToCheck)
  {
    ...
  }
}

Надеюсь, у вас теперь есть представление о Extension-Methods и о том, как вы могли бы использовать их для очень простого решения вашей проблемы;)

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