C# List overwrites itself

Help me understand something please. :slight_smile:

I’m parsing a csv file into a dictionary of lists. I’ve been trying with this code for hours, but every time I print my output I only end up with the last list filling every slot in the dictionary.

public static Dictionary<int, List<string[]>> prefixes = new Dictionary<int, List<string[]>>();
List<string[]> currentGroup = new List<string[]>();

while ((line = reader.ReadLine()) != null) {
    row = line.Split(',');
    if (count <= 1) {
        header.Add(row);
    }
    else {
        curIndex = int.Parse(row[0]);
        if (curIndex != lastIndex) {
            prefixes.Add(lastIndex, currentGroup);
            currentGroup.Clear();
        }
        currentGroup.Add(row);
        lastIndex = curIndex;
    }
    count++;
}

// Add the remaining group
prefixes.Add(lastIndex, currentGroup);

That is I have for example in my file:

0, abc, 123
1, def, 456

and expect it to output the same, but instead I get:

1, def, 456
1, def, 456

For some reason I decided to try replacing currentGroup.Clear() with currentGroup = new List<string[ ]>(); and everything worked!

public static Dictionary<int, List<string[]>> prefixes = new Dictionary<int, List<string[]>>();
List<string[]> currentGroup = new List<string[]>();

while ((line = reader.ReadLine()) != null) {
    row = line.Split(',');
    if (count <= 1) {
        header.Add(row);
    }
    else {
        curIndex = int.Parse(row[0]);
        if (curIndex != lastIndex) {
            prefixes.Add(lastIndex, currentGroup);
            currentGroup = new List<string[]>(); //////////////// Replaced Clear() with new List
        }
        currentGroup.Add(row);
        lastIndex = curIndex;
    }
    count++;
}

// Add the remaining group
prefixes.Add(lastIndex, currentGroup);

Can someone please shed some light on why this is happening? Is Clear actually clearing the List that is already added to my Dictionary as well? Is this a C# feature or a programming feature? :stuck_out_tongue: I’m very confused, but mostly happy that I managed to find the problem after spending hour after hour staring at this tiny piece of code. I just want to avoid making the same mistake again later on.

Is Clear actually clearing the List that is already added to my Dictionary as well?

Exactly. A List<> is a reference object, you can have multiple references to the same List<>

In your code, you have two references to the List<>
One is stored in your dictionary, the other is the local variable “currentGroup.”

Clear() is a method on the List itself, not the variable currentGroup - so you are clearing the List<> object held both in the “currentGroup” variable as well as the Dictionary (since they are both referencing the same object).

When you say “currentGroup = new List<string[ ]>();” however, you are making that variable reference a new List<> object - your old List<> object (which is still stored in your dictionary) is not touched.

The list added to “prefixes” was still the same item you were clearing.

The last index of prefixes was pointing to the same list that currentGroup was pointing to. You cleared the list using the currentGroup pointer. This means that the last index of prefixes is pointing to an empty list and you repeat this process until the last one… the last time you skip the clear call and so every index of “prefixes” points to the same list.

Bollocks. :stuck_out_tongue:

Ohh well, now I know. At least I didn’t have to spend another night thinking about that stupid code and can actually progress now. :slight_smile:

Thanks.

A good idea when learning a new programming language is always to scroll through some sort of reference book (there are many also by the original authors [or their related people] of C#)…

My colleague told me that as well, but that’d be sort of like reading the manual, right? Who does that? :smile:

Death to the manual!