对象引用未设置为对象的实例

5

I have a class Cell:

public class Cell
{
    public enum cellState
    {
        WATER,
        SCAN,
        SHIPUNIT,
        SHOT,
        HIT
    }

    public Cell()
    {
        currentCell = cellState.WATER;
        MessageBox.Show(currentCell.ToString());
    }

    public cellState currentCell { get; set; }
}

我随后尝试在以下类中使用它:
public class NietzscheBattleshipsGameModel
{
    private byte MAXCOL = 10;
    private byte MAXROW = 10;

    public Cell[,] HomeArray;

    private Cell[,] AwayArray;

    public NietzscheBattleshipsGameModel()
    {
        HomeArray = new Cell [MAXCOL, MAXROW];

        AwayArray = new Cell [MAXCOL, MAXROW];
    }


    public string alphaCoords(Int32 x)
    {
        if (x < 0 || x > 9)
        {
            throw new ArgumentOutOfRangeException();
        }

        char alphaChar = (char)('A' + x);

        return alphaChar.ToString();
    }

    public void test()
    {
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {

                // Object reference not set to an instance of an object.
                MessageBox.Show(HomeArray[i,j].currentCell.ToString());
                ///////////////////////////////////////////////////////

            }
        }
    }
}

在上面的代码中,我遇到了对象引用未设置为对象实例(在/////之间)。

我尝试创建一个单一的Cell实例,它可以正常工作。


1
补充之前的回答:如果你声明一个public struct Cell而不是一个class,那么在这些循环中你就不必逐个使用new()来初始化它们,因为struct是值类型,因此总是使用其成员的默认值进行初始化。 - herzmeister
4个回答

12
当您实例化一个数组时,数组中的项将收到该类型的默认值。因此,对于
T[] array = new T[length];

对于每个满足 0 <= i < lengthi,我们都有 array[i] = default(T)。因此,对于引用类型,array[i] 将会是 null。这就是为什么您看到了 NullReferenceException。在您的情况中,Cell 是一个引用类型,所以由于您有

HomeArray = new Cell [MAXCOL, MAXROW]; 

你所做的只是建立了一个指向 Cell 的引用数组,但你从未将这些引用分配给 Cell 实例。也就是说,你告诉编译器“给我一个可以容纳对 Cell 引用的数组”,但你没有告诉编译器“给我一个可以容纳对 Cell 引用并将每个引用分配给一个新的 Cell 实例的数组”。因此,编译器会将这些引用的初始值设置为 null。因此,你需要初始化 HomeArray

for (int i = 0; i < MAXCOL; i++)  { 
    for (int j = 0; j < MAXROW; j++)  { 
        HomeArray[i, j] = new Cell();
    } 
}

4

您需要初始化数组中的单元格。

public NietzscheBattleshipsGameModel()
{
    HomeArray = new Cell[MAXCOL, MAXROW];
    AwayArray = new Cell[MAXCOL, MAXROW];

    for (int i = 0; i < MAXROW; i++)
    {
        for (int j = 0; j < MAXCOL; j++)
        {
            HomeArray[i,j] = new Cell();
            AwayArray[i,j] = new Cell();
        }
    }
}

啊,好的,我明白了。我以为只是声明就够了。感谢大家的好建议。 - iTEgg

3

数组被初始化为空 - 空引用是因为HomeArray[i,j]是空的,而不是因为HomeArray[i,j].currentCell是空的。

更新:如果您有一个语句,其中几个不同的东西可能为null,则通常会将其拆分成多行,以便更容易确定哪些内容为空。

例如,在您的情况下:

MessageBox.Show(HomeArray[i,j].currentCell.ToString());

HomeArray[i,j]HomeArray[i,j].currentCell都有可能为null并触发NullReferenceException异常——无法从异常中判断到底是哪一个。但如果将该语句拆开:

Cell cell = HomeArray[i,j].currentCell;
MessageBox.Show(cell.ToString());

在这种情况下,如果HomeArray[i,j]为空,则在第一行会出现NullReferenceException,而如果cell为空,则会在第二行出现。

我明白了一部分:数组被初始化为空。但是我不理解其余的内容,抱歉。请您再详细说明一下。 - iTEgg
@ikurtz - 我稍微调整了我的答案,现在更清晰了吗? - Justin

0
你遇到异常是因为你没有将Cell的实例分配给矩阵中的任何一个插槽。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接