0

我正在学习使用 as 运算符,我的目标是创建一个选项窗口(非窗口形式),它可以:

添加选项(为了灵活性,以防我想使用 if 语句添加菜单项) 能够显示文本、纹理或类(使用类绘制功能) 通过主机 GameState 进行控制

我还没有添加用于指示已选择项目的选项,对于没有发布完整的作品,我深表歉意。我还没有将代码分类到区域中。再次抱歉!

从性能和可读性(非意大利面条代码)的角度来看,我的代码(特别是 draw 函数)是否正确使用 is 和 as 运算符?

public class OptionWindow : DrawableGameComponent
{
    public Dictionary<int, Option> options;
    int selectedOption;
    bool windowLoops;
    Rectangle drawRectangle;
    int spacer;
    int totalItemHeight;
    SpriteFont sf;
    SpriteBatch sb;

    public Rectangle DrawRectangle
    {
        get { return drawRectangle; }
        set { drawRectangle = value; }
    }

    public int SelectedOption
    {
        get { return selectedOption; }
        set
        {
            if (windowLoops)
            {
                if (selectedOption >= options.Count())
                    selectedOption = 0;
                if (selectedOption < 0)
                    selectedOption = options.Count() - 1;
            }
            else
            {
                if (selectedOption >= options.Count())
                    selectedOption = options.Count() - 1;
                if (selectedOption < 0)
                    selectedOption = 0;
            }
        }
    }

    public OptionWindow(Game game, bool windowLoops, SpriteFont sf, Rectangle drawRectangle)
        : base(game)
    {
        options = new Dictionary<int, Option>();
        this.windowLoops = windowLoops;
        this.sf = sf;
        DrawRectangle = new Rectangle(drawRectangle.X, drawRectangle.Y, drawRectangle.Width, drawRectangle.Height);
    }
    public void Add(object option, bool selectable, bool defaultSelection, int height)
    {
        options.Add(options.Count(), new Option(selectable, option, height));
        if (defaultSelection)
            SelectedOption = options.Count() - 1;
        UpdatePositions();
    }
    public void UpdatePositions()
    {
        UpdateTotalItemHeight();
        if (options.Count() - 1 != 0)
            spacer = (drawRectangle.Height - totalItemHeight) / (options.Count() - 1);
        for (int i = 0; i < options.Count(); i++)
        {
            if (i == 0)
                options[i].Position = new Vector2(drawRectangle.X, drawRectangle.Y);
            else
            {
                options[i].Position = new Vector2(
                    drawRectangle.X,
                    options[i - 1].Position.Y + options[i - 1].Height + spacer);
            }
        }
    }
    public void UpdateTotalItemHeight()
    {
        totalItemHeight = 0;
        for (int i = 0; i < options.Count(); i++)
        {
            totalItemHeight += options[i].Height;
        }
    }
    protected override void LoadContent()
    {
        sb = new SpriteBatch(GraphicsDevice);
        base.LoadContent();
    }
    public override void Draw(GameTime gameTime)
    {
        for (int i = 0; i < options.Count(); i++)
        {
            if (options[i].OptionObject is string)
                sb.DrawString(sf, options[i].OptionObject as string, options[i].Position, Color.White);
            if (options[i].OptionObject is Texture2D)
                sb.Draw(options[i].OptionObject as Texture2D,
                    new Rectangle(
                        (int)options[i].Position.X,
                        (int)options[i].Position.Y,
                        options[i].Height,
                        (options[i].Height / (options[i].OptionObject as Texture2D).Height) * (options[i].OptionObject as Texture2D).Width),
                        Color.White);
            if (options[i].OptionObject is DisplayObject)
                (options[i].OptionObject as DisplayObject).Draw(gameTime);
        }
        base.Draw(gameTime);
    }
}

public class Option
{
    bool selectable;
    object optionObject;
    int height;
    Vector2 position;
    public bool Selectable
    { 
        get { return selectable; }
        set { selectable = value; }
    }
    public object OptionObject
    {
        get { return optionObject; }
        set { optionObject = value; }
    }
    public int Height
    {
        get { return height; }
        set { height = value; }
    }
    public Vector2 Position
    {
        get { return position; }
        set { position = value; }
    }
    public Option(bool selectable, object option, int height)
    {
        Selectable = selectable;
        OptionObject = option;
        Height = height;
    }
}
4

1 回答 1

4

永远不建议使用isthen as。通常的方法是使用以下任一方法:

  • 只需使用is(如果您只想知道类型而不进行后续转换)
  • 将结果分配给as变量并检查该变量是否(不是)null

代码分析工具FxCop可帮助您找到代码中的任何使用点is,然后as由于性能问题向您发出警告。

Note however that a better approach altogether might be to declare your OptionObject property as some abstract class with a Draw method. You could then derive a subclass for strings, one for Texture2D instances and another one for DisplayObject instances and just call Draw in your OptionWindow.Draw method. This would leave the decision which actual drawing operations to execute up to built-in polymorphism features of the framework.

于 2012-09-12T06:47:01.460 回答