0

I'm coding a little plugin for a software using Windows Forms in C#. I need to parse an XML file to retrieve some objects and add them into a ListBox. The problem is that at the end of my program, all objects are the same as the last one added. I kind of figured out why, but I'm still searching how to resolve it. Here is a little example with a String[] instead of my objects:

static void Main(string[] args)
{
    ListBox listbox = new ListBox();
    String[] s = new string[] { "5", "2", "3" };
    listbox.Items.Add(s);
    s[2] = "0";
    listbox.Items.Add(s);

    Console.WriteLine(((String[])listbox.Items[0])[2]); // result => 0
    Console.WriteLine(((String[])listbox.Items[1])[2]); // result => 0
    Console.ReadLine();
}
Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
  • That's because you add the same array reference, so when you update the array, the references you added to the list box point at the same changed array. You need to create a new array if you want to avoid this. – juharr Sep 18 '18 at 15:31
  • Thanks everyone for the suggestions ! I will give it a shot. :) – Kian Soltani Sep 18 '18 at 15:54

3 Answers3

0

With listbox.Items.Add(s); you are adding only one item being the array itself. Use AddRange instead to add the elements of the array.

listbox.Items.AddRange(s);

Another way to make it work is to set the DataSource:

listbox.DataSource = s;

Let's see what happens in your codeh in detail (with line numbers)

1    String[] s = new string[] { "5", "2", "3" };
2    listbox.Items.Add(s);
3    s[2] = "0";
4    listbox.Items.Add(s);
  1. An array is created and initialized.
  2. This array is added as one single item to the ListBox. Note that the array is a reference type. So indeed, you are only adding a reference to the ListBox, not a copy of the array.
  3. One element of the array is changed. This affects the first item added to the ListBox as well, since it contains a reference to this unique array.
  4. The same array-reference is added as an item to the ListBox. Now the ListBox contains 2 items referencing the same array with the same elements.

If you want the items to contain 2 distinct arrays, you can clone the array:

string[] s = new string[] { "5", "2", "3" };
listbox.Items.Add(s);
var s2 = (string[])s.Clone();
s2[2] = "0";
listbox.Items.Add(s2);

Now you have two distinct items in the ListBox. Note that the Array.Clone Method creates a shallow clone. I.e. the array elements themselves are not cloned. So, if they are reference types, both arrays will contain the same objects just after cloning. But since you have 2 distinct arrays, you can replace elements of an array without affecting the other array.

You can add a clone method to your own classes

public class MyOwnClass
{
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }

    public MyOwnClass ShallowClone()
    {
        return (MyOwnClass)MemberwiseClone();
    }
}

MemberwiseClone is inherited from System.Object.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

ListBoxes use pointers, updating the value in the first array you are updating the value of the pointer labled "s", in order to use the same value name but different arrays you have to clone the starting array

ListBox listbox = new ListBox();
String[] s = new string[] { "5", "2", "3" };
listbox.Items.Add(s);
s = (String[])s.Clone();
s[2] = "0";
listbox.Items.Add(s);
Console.WriteLine(((String[])listbox.Items[0])[2]); // result => 3
Console.WriteLine(((String[])listbox.Items[1])[2]); // result => 0
Console.ReadLine();
Ivan Bertola
  • 301
  • 1
  • 3
  • 12
-1

It is showing the last updated values because string are of reference types which will replace the all existing references on update. So you need create new array and then add to the list box as source.

  static void Main(string[] args)
   {
    ListBox listbox = new ListBox();
    String[] s = new string[] { "5", "2", "3" };
    listbox.Items.Add(s);
    String[] s2 = new string[] { "5", "2", "0" };
    listbox.Items.Add(s2);

    Console.WriteLine(((String[])listbox.Items[0])[2]); // result => 0
    Console.WriteLine(((String[])listbox.Items[1])[2]); // result => 0
    Console.ReadLine();
   }
Arun Kumar
  • 885
  • 5
  • 11