-5

I found a curious effect in some code I wrote that I don't understand. I found a workaround but I'd like to know why the original code doesn't work as expected.

So populating a jagged array, I tried to define each cell individually. This resulted in 10 copies of the last array defined. From this code:

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

Whereas when using a single dimension array as an intermediate, the data saved as expected. By which I mean there were 10 unique arrays saved in the jagged array. From this code:

        for (int i = 0; i < 10; i++)
        {
            int[] scoreArray = { _highScores[i].date, _highScores[i].score, _highScores[i].questionsAsked };
            serialisableHighScores.scores[i] = scoreArray;
        }
Era
  • 171
  • 1
  • 5
  • 13
  • 2
    That is a *jagged array* - a multidimensional array would look like `scores[i, 0]`. – NightOwl888 Feb 21 '18 at 22:42
  • 1
    Why not just make a HighScore object with your 3 attributes? Then make a single array, list, whatever collection of your objects? It is easier to work with attribute names in code than it is to try and remember which value is in which index of an array...Also there are myriad examples of how to serialize/deserialize objects. – user7396598 Feb 21 '18 at 22:55
  • @NightOwl888 Thanks, I had the wrong name obviously – Era Feb 22 '18 at 10:11
  • @user7396598 I'm learning one thing at a time. I only used the jagged array for saving with a binary formatter. Aside from the update and load functions, the score object is used everywhere – Era Feb 22 '18 at 10:14

1 Answers1

-1

The reason is that a jagged array is actually an array of arrays of values.

Since arrays are objects, reference types, it means that if you construct a jagged array with room for 10 arrays, all those array references are initialized to null.

In other words:

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

throws NullReferenceException.

The code can be thought of like this:

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

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

Either you assign a fully populated array into the first slot, or you assign an initialized array without the values, like this:

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

Now, that's just the explanation of why it crashes on your end. The best option you have available is not to use arrays like this, that is, don't use 2-dimensional arrays to keep one list of related values, instead use objects:

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

Additionally, arrays are good for fixed size things but in general it's usually better to use lists:

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

Though given the name of your variable, if you need to adhere to some badly designed (my opinion) serializing format with arrays of arrays it's probably better to just stick with your code.

Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
  • That explains it clearly. Thank you. In debugging I wasn't receiving the NullReferenceError for some reason. This is my first time serialising data and I have already thought of several ways that I would change that code if I were to start a different project. – Era Feb 22 '18 at 23:57