C#对象丢失了它的引用并变为空

时间:2018-02-18 10:33:21

标签: c# object null

以下是我的课程的简化代码:

public class Game
{
    World world;
    DataManager dataManager;
    public Game()
    {
        world = new World();
        dataManager = new DataManager();
    }

    public void Run()
    {
        Menu mainMenu = new Menu(dataManager,world);
        //world = dataManager.LoadFile("Games\\test game.xml");
        //the commented line above is correcting my bug but I don't want
        //to do it that way.
        List <Location> locs = world.GetAllLocations();
        //when the debug mode arrives at this point, world is empty.
    }
}

public class Menu
{
    DataManager dataManager ;
    World world;
    public Menu(DataManager _dataManager, World _world)
    {
        this.dataManager = _dataManager;
        this.world = _world;
        world = dataManager.LoadFile("Games\\test game.xml");
        //the world is filled correctly here above.
    }
 }

两个类共享相同的命名空间。 我的dataManager用xml填充世界,这是完美的工作。 这个世界应该是game.world属性的参考,但是一旦我们回到游戏类中它似乎就变得空洞了......

当程序以这种方式表现时,我真的不明白。 如果您需要更多信息,请参阅以下内容:

https://github.com/mikyjax/TextAdventureGameEditor/tree/master/Text%20Adventure%20Engine

2 个答案:

答案 0 :(得分:4)

这不是引用如何工作。

  1. new Menu(dataManager,world);&lt; =您调用构造函数并传入构造函数中创建的world实例(这与传入引用不同)。< / LI>
  2. this.world = dataManager.LoadFile("Games\\test game.xml")&lt; =创建一个新实例(所以新指针)并分配给局部变量world。不会发生的是run中的调用方法现在共享相同的world实例,仍然是null
  3. 如果这是您的意图,您必须使用ref关键字(或out)。

    public Menu(DataManager _dataManager, ref World _world)

    并用

    调用它

    new Menu(dataManager,ref world);

    那说这是两个级别的不良做法。

    1. 您的构造函数不应该有副作用
    2. 如果要创建一个在对象之外使用的对象(比如在工厂中),那么你应该有一个专用的方法,然后将该对象作为方法的返回返回。
    3. public class Menu {
          DataManager dataManager ;
          World world;
          public Menu(DataManager _dataManager)
          {
              this.dataManager = _dataManager;
          }
      
          public World CreateWorld() {
              if(this.world == null)
                  this.world = dataManager.LoadFile("Games\\test game.xml");
              return this.world;
          }
      }
      
      
      public class Game {
          World world;
      
          public void Run()
          {
              Menu mainMenu = new Menu(dataManager);
              this.world = mainMenu.CreateWorld();
          }
      }
      

答案 1 :(得分:1)

您的代码类似于:

A = B
A = C

然后你想知道为什么B也不是C:你设置Menu.World = _world然后重写Menu.Wold就是你从xml加载的内容:{{ 1}}未经修改。

为什么_world构造函数完全填充世界 - 这不是它唯一的责任 - 是吗?

我会将您的静态Menu重命名为LoadFile,然后在创建菜单之前在CreateWorld(..filename..)方法中调用它。这样您就可以将准备好的Run提供给Menu构造函数。

我仍然想知道的是,为什么菜单需要访问您的原始数据......