C#:为什么需要使用中间数组来定义交错数组?

C#: Why does an intermediate array need to be used for defining a jagged array?

我在我写的一些我不理解的代码中发现了一个奇怪的效果。我找到了解决方法,但我想知道为什么原始代码无法按预期工作。

所以填充一个交错的数组,我试图单独定义每个单元格。这导致最后定义的数组有 10 个副本。来自这段代码:

        for (int i = 0; i < 10; i++)
        {
            serialisableHighScores.scores[i][0] = _highScores[i].date;
            serialisableHighScores.scores[i][1] = _highScores[i].score;
            serialisableHighScores.scores[i][2] = _highScores[i].questionsAsked;
        }

而当使用一维数组作为中间值时,数据按预期保存。我的意思是锯齿状数组中保存了 10 个独特的数组。来自这段代码:

        for (int i = 0; i < 10; i++)
        {
            int[] scoreArray = { _highScores[i].date, _highScores[i].score, _highScores[i].questionsAsked };
            serialisableHighScores.scores[i] = scoreArray;
        }

原因是交错数组实际上是值数组的数组。

由于数组是对象,引用类型,这意味着如果您构造一个锯齿状数组,其中有 10 个数组的空间,所有这些数组引用都将初始化为 null

换句话说:

int[][] a = new int[10][];
a[0][0] = 10;

抛出 NullReferenceException.

代码可以这样想:

int[][] a = new int[10][];

int[] temp = a[0]; // this works, but temp is now null
temp[0] = 10;      // throws NullReferenceException

要么将一个完全填充的数组分配到第一个槽中,要么分配一个没有值的初始化数组,如下所示:

for (int i = 0; i < 10; i++)
{
    serialisableHighScores.scores[i] = new int[3];
    serialisableHighScores.scores[i][0] = _highScores[i].date;
    serialisableHighScores.scores[i][1] = _highScores[i].score;
    serialisableHighScores.scores[i][2] = _highScores[i].questionsAsked;
}

现在,这就是为什么它会在您这边崩溃的原因。您可用的最佳选择是不要使用这样的数组,即不要使用二维数组来保留一个相关值列表,而是使用对象:

public class Score
{
    public Score(DateTime date, int score, int questionsAsked)
    {
        Date = date;
        Score = score;
        QuestionsAsked = questionsAsked;
    }

    public DateTime Date { get; }
    public int Score { get; }
    public int QuestionsAsked { get; }
}

此外,数组适用于固定大小的事物,但通常使用列表通常更好:

var serializableHighScores = new List<Score>();
for (int i = 0; i < 10; i++)
{
    serializableHighScores.Add(new Score(_highScores[i].date, _highScores[i].score, _highScores[i].questionsAsked));
}

虽然 给出了变量的名称,但如果您需要使用一些设计糟糕的(我认为)序列化格式的数组,那么最好坚持使用您的代码。