试图制作2D列表

时间:2009-08-06 19:16:29

标签: c# arrays list

我正在尝试编写一个包含数字生物的模型。在模型中,我将环境置于固定的二维阵列中,但每个细胞需要包含其中的生物列表。我尝试使用锯齿状数组,但由于整个程序运行中占用元素的数量变化很大,我需要使用比数组更灵活的东西。我已经尝试制作类型列表的二维数组,但我得到它的错误。

    List<Creature>[,] theWorld;


    public Environment()
    { 
        List<Creature>[,] theWorld = new List<Creature>[100,100];
    }

    public void addCreature(Creature c)
    {
       for (int x = 0; x < 100; x++)
        {
            for (int y = 0; y < 100; y++)
            {
                theWorld[x, y].Add (c);

            } } }

这是我试图在开头声明数组的片段,作为保存(生物体)列表的类型,稍后我尝试将生物(c)添加到每个列表中数组的元素。

当我运行它时,我收到以下错误消息 -

“HGT_sim_2.exe中发生了'System.NullReferenceException'类型的未处理异常

附加信息:对象引用未设置为对象的实例。“

和“World [x,y] .Add(c);”突出显示。

如果有人能告诉我我做错了什么,甚至更好,解决这个问题,那就太棒了。 谢谢你提前!

6 个答案:

答案 0 :(得分:8)

最初包含的所有数组都是很多空值。你需要实际创建列表......

for(int x = 0 ; x < 100 ; x++)
    for(int y = 0 ; y < 100 ; y++)
        theWorld[x,y] = new List<Creature>();

但就个人而言,我认为这将是一种昂贵的做事方式......

部分取决于数据是否“稀疏” - 即通常采用的大多数细胞?例如,一种简单(但可能更有效)的方法是使用类似多地图的方法;即。

Point pt = new Point(x,y);
theWorld.Add(pt, someCreature);

其中theWorld可能类似EditableLookup<Point, Creature>(使用“MiscUtil”中的EditableLookup<,>)。这样,您仍然可以通过坐标查询它,并在坐标上有多个生物,但您不必为每个细胞分配空间。因为它作为字典起作用,它仍然很快。不像那样快速作为平面阵列,但它会缩放到更大(稀疏)的网格......当然,如果网格在每个单元格上都有生物,那么它可能更多昂贵!因此需要了解您的数据。

答案 1 :(得分:3)

您需要初始化数组的每个成员,例如

for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            theWorld[x, y] = new List<Creature>();

        } }

答案 2 :(得分:2)

以下是修复:

List<Creature>[,] theWorld;


public Environment()
{ 
    theWorld = new List<Creature>[100,100]; // Remove the type, you were creating a new list and throwing it away...

    for(int x = 0 ; x < 100 ; x++)
       for(int y = 0 ; y < 100 ; y++)
          theWorld[x,y] = new List<Creature>();    
}

public void addCreature(Creature c)
{
   for (int x = 0; x < 100; x++)
    {
        for (int y = 0; y < 100; y++)
        {
            theWorld[x, y].Add (c);

        } } }

答案 3 :(得分:0)

您已创建数组对象来保存列表,但您尚未创建列表本身。您需要在构造函数中执行以下操作:

for (int x = 0; x < 100; x++) 
    for (int y = 0; y < 100; y++)
        theWorld[x,y] = new List<Creature>();

另一个问题:您还在构造函数中将theWorld定义为局部变量,这意味着theWorld上的Environment字段也从未初始化。

然而,10,000 List可能对你真正需要的东西有点过分。如果您的环境确实需要每个点Creature,并且某些生物可能会移动到其他点(一个点上有多个点),那么使用Dictionary<Point, IList<Creature>>作为您的更有意义模型与10,000个列表。

public void Add(Creature c, Point at)
{
    IList<Creature> list;
    if (!theWorld.TryGetValue(at)) {
        list = theWorld[at] = new List<Creature>();
    }
    list.Add(c);
}

然后,您可以类似地实施MoveRemove方法。另外,请注意您将相同的生物添加到每个点,这可能意味着您的环境中的所有点都有一个生物。您可能希望为每个点创建new Creature(),如果这是您实际建模的内容。

答案 4 :(得分:0)

执行此操作时:

List<Creature>[,] theWorld = new List<Creature>[100,100];

您正在创建一个List<Creature>引用数组,但它们都是空的(指向null,而不是有效的List)。您需要初始化每个元素:

for (int x = 0; x < 100; x++) {
    for (int y = 0; y < 100; y++) {
       theWorld[i,j] = new List<Creature>();
    }
}

完成后,您就可以致电。添加个人会员。

答案 5 :(得分:0)

你这样做几乎是正确的。您的变量是List<Creature>的2D数组。现在,List<Creature>是一个引用类型,因此数组被初始化为在其所有成员中包含null。这样就得到了NullReferenceException。这条线

theWorld[x, y].Add (c);

基本等同于

null.Add (c);

您需要做的就是初始化所有成员以包含List<Creature>的实例。执行此操作的最佳方法是在构造函数中。只需像这样重写它:

public Environment()
{ 
    theWorld = new List<Creature>[100,100];
    for(int x = 0 ; x < 100 ; x++)
        for(int y = 0 ; y < 100 ; y++)
            theWorld[x,y] = new List<Creature>();
}

现在所有操作都将按预期工作。

另请注意,在您的示例中,您正在创建一个与类成员同名的局部变量。这样就不会初始化类成员 - 它保持为null。