C# 试图制作一个二维列表数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1240805/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:04:23  来源:igfitidea点击:

Trying to make a 2D array of lists

c#arrayslist

提问by

I'm trying to write a model containing digital organisms. Within the model i'd liek the environment to be a fixed 2-d array, but each cell needs to contain a list of the organisms in it. I tried using a jagged array, but as the number of occupied elements varies quite a bit throughout the programm run, i need to use something more flexible than an array. I've tried making a 2-D array of the type list, but im getting errors with it.

我正在尝试编写一个包含数字生物的模型。在模型中,我认为环境是一个固定的二维数组,但每个单元格都需要包含其中的生物列表。我尝试使用锯齿状数组,但由于在整个程序运行过程中占用元素的数量变化很大,我需要使用比数组更灵活的东西。我尝试制作类型列表的二维数组,但我遇到了错误。

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

            } } }

this is the segment where i'm trying to declare the array at the beginning, as a type that holds lists (of the organisms), and later i try to add a creature (c) to each of the lists in each element of the array.

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

when i run it i get the following error message-

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

"An unhandled exception of type 'System.NullReferenceException' occurred in HGT_sim_2.exe

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

Additional information: Object reference not set to an instance of an object."

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

and the line "World[x, y].Add (c);" is highlighted.

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

If anyone can tell me what i'm doing wrong, and even better, a way around the problem, it'd be amazing. thank you ain advance!

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

回答by ConsultUtah

Here's the fix:

这是修复:

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

        } } }

回答by Jason

You have created the array object to hold your lists, but you haven't created the list itself. You will need to do the following in your constructor:

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

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

Another problem: you were also defining theWorldas a local variable in your constructor, which means your theWorldfield on Environmentwas never initialized, either.

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

However, 10,000 Lists may be overkill for what you really need. If your Environment really needs a Creatureat every point, and some Creatures may move to other points (where there is more than one at a point, then it may make more sense to use a Dictionary<Point, IList<Creature>>as your model versus 10,000 lists.

但是,List对于您真正需要的东西,10,000秒可能有点过分。如果您的环境确实Creature在每个点都需要一个,并且一些生物可能会移动到其他点(在一个点上有多个生物,那么使用 aDictionary<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);
}

You can then implement Moveand Removemethods similarly. Also, note that you are adding the sameCreature to every point, which (may) mean that there's one Creature at all points in your Environment. You will probably want to create a new Creature()for every point, if that's what you are actually modeling.

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

回答by Marc Gravell

All your array contains initially is a lot of nulls. You need to actually create the lists...

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

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

Personally, though, I expect this will be a costly way to do things...

不过,就我个人而言,我预计这将是一种代价高昂的做事方式......

It depends in part on whether the data is "sparse" - i.e. are most of the cells usually taken? A simple (but possibly more efficient) approach, for example, would be to use something like multi-map; i.e.

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

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

where theWorldcould be something like EditableLookup<Point, Creature>(using EditableLookup<,>from "MiscUtil"). That way, you can still query it by co-ordinate, and have multiple creatures ona coordinate, but you don't have to allocate space for every cell. And because it functions as a dictionary it is still fast. Not asfast as a flat array, but it will scale to bigger (sparse) grids... of course, if the grid has creatures on every cell it could be moreexpensive! Hence the need to understand your data.

哪里theWorld可能是这样的EditableLookup<Point, Creature>(使用EditableLookup<,>来自“ MiscUtil”)。这样,您仍然可以通过坐标查询,并一个坐标有多个生物,但您不必为每个单元格分配空间。而且因为它可以作为字典,所以速度仍然很快。不像平面阵列那么快,但它会扩展到更大(稀疏)的网格……当然,如果网格在每个单元格上都有生物,它可能会贵!因此需要了解您的数据。

回答by Eric J.

You need to initialize each member of your array, e.g.

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

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

        } }

回答by Reed Copsey

When you do this:

当你这样做时:

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

You're creating an array of List<Creature>references, but they are all empty (pointing to null, not a valid List). You need to initialize each individual element:

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

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

Once you've done that, you'll be able to call .Add on the individual members.

完成此操作后,您将能够对单个成员调用 .Add。

回答by Vilx-

You're doing it almost correct. Your variable is a 2D array of List<Creature>. Now, List<Creature>is a reference type, so the array is initialized to contain null's in all its members. Thus you get the NullReferenceException. The line

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

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

is basically equivalent to

基本上相当于

null.Add (c);

All you need to do is to initialize all the members to contain instances of List<Creature>. The best way to do this would be in the constructor. Just rewrite it like this:

您需要做的就是初始化所有成员以包含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>();
}

Now all the operations will work as expected.

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

Also note, that in your example you are creating a local variable with the same name as the class member. This way you don't initialize the class member at all - it stays null.

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