初始化数组后出现空引用异常

Nullreferenceexception after initializing an array

我一直在尝试在 XNA 中制作测试游戏(visual studio 2015),但每次我加载它时都会收到 NullReferenceException,即使我实际上已经初始化了它。这是它的一个非常简短的版本...

    namespace Overbox
    {
        public class Player
        {
             private Player[] characterList = new Player[14];

             virtual public void Initialize()
             {
                  //characterList = new Player[14];
                  characterList[0] = new Hero();

                  //for (int i = 0; i <= characterList.Length; i++)
                  //    characterList[i].Initialize();
                  characterList[0].Initialize();
             }
    }
    virtual public void Draw(SpriteBatch spriteBatch, Texture2D texture)
    {
        //for (int i = 0; i <= characterList.Length; i++)
        //{
        //    if (characterList[i].Active)
        //        characterList[i].Draw(spriteBatch, texture);
        //}
        characterList[0].Draw(spriteBatch, texture); //Here the error occurs
    }



   }
}

如果有人出于任何原因想要整个 class 我可以编辑它,但这是我能找到的所有相关代码。

编辑:堆栈跟踪

Overbox.exe!Overbox.Player.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch, Microsoft.Xna.Framework.Graphics.Texture2D texture) Line 53 C# Overbox.exe!Overbox.MediaHandler.Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) Line 54 C#

Overbox.exe!Overbox.Program.Main(string[] args) Line 15 C#

一切都应该在那里。

英雄 class:

    namespace Overbox.Characters
    {
         class Jacketed : Player
         {
         override public void Initialize()
         {
                //Unrelated setting of variables
         }
         public override void Draw(SpriteBatch spriteBatch, Texture2D texture)
         {
                spriteBatch.Draw(texture, PlayerPosition, Color.White);
         }
    }
}

非常短的游戏循环版本class:

  public class Game1 : Microsoft.XNA.Framework.Game
  {
        public static Player player;
        //I do load the content which playerTexture requires before anyone asks about it
        private Texture2D playerTexture;


        protected override void Initialize()
        {
               player = new Player();
               player.Initialize();
        }
        protected override void Draw(GameTime gameTime)
        {
               spriteBatch.Begin();

               player.Draw(spriteBatch, playerTexture);

               spriteBatch.End();
        }
  }
private Player[] characterList = new Player[14];

创建一个Player 数组,但实际上并不构造对象。所以你最终得到的基本上是一个充满空值的数组。

您缺少这样的内容:

public Player()
{
    foreach (var character in characterList)
    {
        character = new Player();
    }
}

这是一个大胆的猜测,但我假设 Hero 覆盖了一个或两个或 InitializeDraw。假设 Hero 看起来像这样:

class Hero : Player
{
    public override void Initialize()
    {
        // Do some stuff. Don't call base.Initialize()
    }
}

所以我们覆盖了 Initialize(),但没有调用 base.Initialize()。我们也没有覆盖 Draw(),因此在 Hero 实例上调用时将使用 Player 中的 Draw()

所以让我们考虑一下什么时候构造一个Player player。那么player.characterList也被创建了,但是它的元素是null。接下来,调用 player.Initialize(),设置 characterList[0] = new Hero()。请注意 characterList[0] 也有自己的 characterList 数组。

接下来要发生的事情是 characterList[0].Initialize()。这在 Hero 中调用了 Initialize() 覆盖。这不会在 Player 中调用 Initialize(),因此 Hero 实例中的 characterList 仍然有 null 个元素。

以后的某个时间,Draw方法在Player中被调用。这反过来调用 characterList[0].Draw(spriteBatch, texture)。由于我们没有覆盖 Hero 中的 Draw 方法,这会调用相同的方法,但在我们的 Hero 实例上。但请记住 HerocharacterList 仍然具有 null 值?好吧,这里唯一发生的事情就是调用 characterList[0].Draw(spriteBatch, texture),正如我们现在所知,它是在 null 值上调用 Draw

这是我对正在发生的事情的猜测。细节可能有所不同,但我想这种事情是根本原因。可以肯定的是,检查异常的堆栈跟踪。您会注意到 Draw 方法的两个框架,让您知道异常发生在对 Draw.

的递归调用中

我想这个解决方案有一段时间了,但由于组织原因我不想这样做。我所要做的就是将 characterList 移动到主游戏循环 class 并使其成为 public,保证在调用 draw 方法之前对其进行初始化。这确实有效。