我在一些我不明白的代码中发现了一种奇怪的效果。我找到了一个解决方法,但我想知道为什么原始代码不能按预期工作。
如此填充锯齿状阵列,我试图单独定义每个单元格。这导致定义了最后一个数组的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;
}
答案 0 :(得分:-1)
原因是锯齿状数组实际上是一组值数组。
由于数组是对象,引用类型,这意味着如果构造一个具有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));
}
虽然给出了变量的名称,如果你需要遵循一些设计糟糕的(我的意见)序列化格式的数组阵列,那么只需坚持你的代码就更好了