C#Singleton stackoverflow

时间:2016-01-23 22:03:22

标签: c# forms singleton

我试图制作一款使用状态机的游戏。 " GameState"通过从" World"中调用getInstance()来创建世界(进入时)这是一个单身人士。

世界单身人士有一个2D列表" Tile"物体(世界由瓷砖制成)。在World类的构造函数中,列表由嵌套的for循环填充,该循环使用SimpleTileFactory类创建切片并将它们放在列表中。

问题是我得到了StackOverflow。我调试了代码,发现World单例的构造函数被多次调用,这可能导致堆栈溢出。我不知道为什么它不止一次被召唤,并且感觉我忽略了一些简单的东西。我的单身人士是否正确?

守则如下。

提前致谢。

GameState Class

public partial class GameState : UserControl, IState<MainView>
{
    private bool ready = false;

    public GameState()
    {
        InitializeComponent();
    }

    public void enter(MainView owner)
    {
        this.Width = owner.Width;
        this.Height = owner.Height;
        this.Location = new Point(0, 0);
        owner.Controls.Add(this);
        World.getInstance();

        this.ready = true;
    }

    public void update(MainView owner)
    {
        this.Refresh();
    }

    public void exit(MainView owner)
    {
        owner.Controls.Remove(this);
    }

    public bool isReady()
    {
        return this.ready;
    }

    private void GameState_Paint(object sender, PaintEventArgs e)
    {
        //for (int i = 0; i < World.getInstance().tiles.Count; i++)
        //{
        //    for (int j = 0; j < World.getInstance().tiles[0].Count; j++)
        //    {
        //        //e.Graphics.DrawImage(new Image(), new Rectangle());
        //    }
        //}
    }
}

世界级

class World
{
    private static World instance;
    public GameResources gameResources;

    public SimpleTileFactory tileFactory;

    public List<List<Tile>> tiles = new List<List<Tile>>();
    public Size worldSize = new Size(100, 100);

    private World()
    {
        this.gameResources = new GameResources();
        this.tileFactory = new SimpleTileFactory();

        for (int i = 0; i < worldSize.Height; i++)
        {
            List<Tile> row = new List<Tile>();
            for (int j = 0; j < worldSize.Width; j++)
            {
                row.Add(tileFactory.createTile(new Point(j, i)));
            }
        }
    }


    public static World getInstance()
    {
        if (instance == null)
        {
            instance = new World();
        }

        return instance;
    }
}

SimpleTileFactory类

class SimpleTileFactory
{
    public SimpleResourceFactory resourceFactory = new SimpleResourceFactory();
    private Random random = new Random();

    private int maxNumOfResourcesPerTile = 5;

    public SimpleTileFactory()
    {

    }


    public Tile createTile(Point location)
    {
        //create tile
        Tile tile = new Tile();
        tile.location = location;

        //give tile terrain type
        Terrain terrain = new Terrain();
        terrain.type = random.Next(0, World.getInstance().gameResources.terrainNames.Count);
        terrain.name = World.getInstance().gameResources.terrainNames[terrain.type];
        terrain.accessability = 1000;

        //add resources to terrain
        int numberOfResources = random.Next(0, maxNumOfResourcesPerTile + 1);

        for (int i = 0; i < numberOfResources; i++)
        {
            terrain.resources.Add(resourceFactory.createTerrainResource(terrain.type));
        }

        tile.terrain = terrain;

        return tile;
    }
}

SimpleResourceFactory Class

class SimpleResourceFactory
{
    public List<string> resourceNames = new List<string>();
    public List<Image> resourceImages = new List<Image>();
    private Random random = new Random();

    public SimpleResourceFactory()
    {
        resourceNames.Add("asdfasfd");
        resourceNames.Add("asdfasfd");
        resourceNames.Add("asdfasfd");
    }


    public TerrainResource createTerrainResource(int terrainType)
    {
        TerrainResource resource = new TerrainResource();
        resource.type = random.Next(0, resourceNames.Count);
        resource.name = this.resourceNames[resource.type];
        resource.amount = 100;

        return resource;
    }
}

瓷砖类

class Tile
{
    public Point location;
    public Terrain terrain;

    public Tile()
    {

    }
}

地形等级

class Terrain
{
    public int type;
    public string name;
    public int accessability;
    public List<TerrainResource> resources = new List<TerrainResource>();

    public Terrain()
    {

    }
}

TerrainResource Class

class TerrainResource
{
    public int type;
    public string name;
    public int amount;

    public TerrainResource()
    {

    }
}

2 个答案:

答案 0 :(得分:0)

createTile正在调用getInstance,并导致溢出:

  

WpfApplication2.exe!WpfApplication2.SimpleResourceFactory.SimpleResourceFactory()第116行C#           WpfApplication2.exe!WpfApplication2.SimpleTileFactory.SimpleTileFactory()第76行C#           WpfApplication2.exe!WpfApplication2.World.World()第49行C#           WpfApplication2.exe!WpfApplication2.World.getInstance()第66行C#           WpfApplication2.exe!WpfApplication2.SimpleTileFactory.createTile(System.Windows.Point位置)第95行C#           WpfApplication2.exe!WpfApplication2.World.World()第56行C#           WpfApplication2.exe!WpfApplication2.World.getInstance()第66行C#           WpfApplication2.exe!WpfApplication2.SimpleTileFactory.createTile(System.Windows.Point位置)第95行C#           WpfApplication2.exe!WpfApplication2.World.World()第56行C#           WpfApplication2.exe!WpfApplication2.World.getInstance()第66行C#           WpfApplication2.exe!WpfApplication2.SimpleTileFactory.createTile(System.Windows.Point位置)第95行C#

答案 1 :(得分:0)

问题是在World构造函数中调用了createTile()。这样,当执行createTile()时,还没有完全创建World对象,然后调用getInstance(),然后再生成一个新的World(因为它尚未完全创建),它再次调用createTile()。这是一个无限循环。

我通过更改World构造函数和createTile()代码快速修复了它,如下所示。这不是解决它的最美妙的方法,所以我可能只是从世界中分离GameResources。

    private World()
    {
        this.gameResources = new GameResources();
        this.tileFactory = new SimpleTileFactory();

        for (int i = 0; i < this.worldSize.Height; i++)
        {
            List<Tile> row = new List<Tile>();
            for (int j = 0; j < this.worldSize.Width; j++)
            {
                row.Add(tileFactory.createTile(new Point(j, i), this));
            }
            this.tiles.Add(row);
        }
    }

createTile方法:

    public Tile createTile(Point location, World world)
    {
        //create tile
        Tile tile = new Tile();
        tile.location = location;

        //give tile terrain type
        Terrain terrain = new Terrain();
        terrain.type = random.Next(0, world.gameResources.terrainNames.Count);
        terrain.name = world.gameResources.terrainNames[terrain.type];
        terrain.accessability = 1000;

        //add resources to terrain
        int numberOfResources = random.Next(0, maxNumOfResourcesPerTile + 1);

        for (int i = 0; i < numberOfResources; i++)
        {
            terrain.resources.Add(resourceFactory.createTerrainResource(terrain.type));
        }

        tile.terrain = terrain;

        return tile;
    }