这是在DrawableGameComponent中有效使用Is和as运算符吗



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

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

我还没有添加指示项目被选中的选项,很抱歉没有发布完整的作品。我还没有将代码按区域排序。再次抱歉!

从性能和可读性(非意大利面条代码)的角度来看,我的代码(尤其是draw函数)是否正确地使用了Is并正确地作为运算符?

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;
    }
}

建议先使用is,然后再使用as。通常的方法是以下任意一种:

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

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

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

相关内容

  • 没有找到相关文章

最新更新