【问题标题】:C#: Why does an intermediate array need to be used for defining a jagged array?C#:为什么需要使用中间数组来定义交错数组?
【发布时间】:2018-08-01 16:09:47
【问题描述】:

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

所以填充一个锯齿状数组,我尝试单独定义每个单元格。这导致定义的最后一个数组有 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;
        }

【问题讨论】:

  • 这是一个锯齿状数组 - 一个多维数组看起来像scores[i, 0]
  • 为什么不使用您的 3 个属性制作一个 HighScore 对象?然后制作一个数组,列表,你的对象的任何集合?在代码中使用属性名称比尝试记住哪个值在数组的哪个索引中更容易......此外还有无数关于如何序列化/反序列化对象的示例。
  • @NightOwl888 谢谢,我的名字显然是错误的
  • @user7396598 我一次只学一件事。我只使用锯齿状数组来保存二进制格式化程序。除了更新和加载功能,分数对象无处不在

标签: c# arrays jagged-arrays


【解决方案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));
}

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

【讨论】:

  • 这解释得很清楚。谢谢你。在调试中,由于某种原因,我没有收到 NullReferenceError。这是我第一次序列化数据,如果我要开始一个不同的项目,我已经想到了几种方法来更改该代码。
猜你喜欢
  • 2011-08-29
  • 2021-11-20
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 2011-11-10
  • 2021-12-20
  • 2012-07-15
  • 2010-12-11
相关资源
最近更新 更多