这是否有效地使用了DrawableGameComponent中的is和as运算符?

时间:2012-09-12 06:39:11

标签: c# menu xna

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

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

我仍然没有添加指示项目被选中的选项,对于没有发布完整作品表示歉意。我还没有将代码分类到区域。对不起!

从性能和可读性(非意大利面条代码)的角度来看,我的代码(尤其是绘图函数)是否正确使用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;
    }
}

1 个答案:

答案 0 :(得分:4)

永远不建议使用is然后使用as。通常的方法是下列之一:

  • 只需使用is(如果您只是想知道没有后续投射的类型)
  • as的结果分配给变量并检查该变量是否为({1}}

代码分析工具FxCop可帮助您找到代码中使用null然后is的任何位置,并因性能问题向您发出警告。

但是请注意,更好的方法可能是将as属性声明为具有OptionObject方法的抽象类。然后,您可以为字符串派生一个子类,一个用于Draw个实例,另一个用于Texture2D个实例,只需在DisplayObject方法中调用Draw即可。这将决定实际的绘图操作执行到框架的内置多态性功能。