Passing an arraylist which contains a struct which contains an arraylist

C

Christopher H

I've been reading about how C# passes ArrayLists as reference and Structs as
value, but I still can't get my program to work like I want it to.

Simple example:


code:------------------------------------------------------------------------------
class Program
{
static public ArrayList MyArrayList = new ArrayList();
static void Main(string[] args)
{

MyArrayList.Add(0);
Console.WriteLine(MyArrayList[0]);
SomeFunction(MyArrayList);
Console.WriteLine(MyArrayList[0]);

Console.ReadLine();
}

static void SomeFunction(ArrayList MyArrayList) {
ArrayList NewArrayList = new ArrayList(MyArrayList);

NewArrayList[0] = 1;
}
}
------------------------------------------------------------------------------

In SomeFunction I create a new ArrayList and not a reference to the old one
(MyArrayList). So when I modify NewArrayList, the change is not reflected in
MyArrayList in Main(). Output:


code:------------------------------------------------------------------------------
0
0
------------------------------------------------------------------------------

Easy enough and works as expected. Here's where I've been going bananas for
the last couple of hours.
It involves an arraylist inside a struct which is itself inside an
arraylist.


code:------------------------------------------------------------------------------
class Program
{
static public ArrayList MyArrayList = new ArrayList();
public struct Struct_Row {
public ArrayList ArrayList_Struct;
};

static void Main(string[] args)
{

Struct_Row testRow = new Struct_Row();
testRow.ArrayList_Struct = new ArrayList();
testRow.ArrayList_Struct.Add(2);
MyArrayList.Add(testRow);

Console.WriteLine(((Struct_Row)MyArrayList[0]).ArrayList_Struct[0]);
SomeFunction(MyArrayList);
Console.WriteLine(((Struct_Row)MyArrayList[0]).ArrayList_Struct[0]);
Console.ReadLine();
}

static void SomeFunction(ArrayList MyArrayList) {
ArrayList NewArrayList = new ArrayList(MyArrayList);

((Struct_Row)NewArrayList[0]).ArrayList_Struct[0] = 3;
}

}
------------------------------------------------------------------------------

Even though I've created a new arraylist in SomeFunction(), when I change
the
value of ArrayList_Struct[0] in SomeFunction(), the change is reflected in
Main() which I don't want :( Output:


code:------------------------------------------------------------------------------
2
3
 
B

Bill Butler

Inline
Christopher H said:
I've been reading about how C# passes ArrayLists as reference and
Structs as
value, but I still can't get my program to work like I want it to.

Simple example:


code:------------------------------------------------------------------------------
class Program
{
static public ArrayList MyArrayList = new ArrayList();
static void Main(string[] args)
{

MyArrayList.Add(0);
Console.WriteLine(MyArrayList[0]);
SomeFunction(MyArrayList);
Console.WriteLine(MyArrayList[0]);

Console.ReadLine();
}

static void SomeFunction(ArrayList MyArrayList) {
ArrayList NewArrayList = new ArrayList(MyArrayList);

NewArrayList[0] = 1;
}
}
------------------------------------------------------------------------------

In SomeFunction I create a new ArrayList and not a reference to the
old one
(MyArrayList). So when I modify NewArrayList, the change is not
reflected in
MyArrayList in Main(). Output:


code:------------------------------------------------------------------------------
0
0

It worked because it was an arraylist of primitive types.
When NewArrayList was created from MyArrayList it did a simple copy of
the elements in the first arraylist to the second arraylist.


Here's where I've been going bananas for the last couple of hours.
It involves an arraylist inside a struct which is itself inside an
arraylist.


code:------------------------------------------------------------------------------
class Program
{
static public ArrayList MyArrayList = new ArrayList();
public struct Struct_Row {
public ArrayList ArrayList_Struct;
};

static void Main(string[] args)
{

Struct_Row testRow = new Struct_Row();
testRow.ArrayList_Struct = new ArrayList();
testRow.ArrayList_Struct.Add(2);
MyArrayList.Add(testRow);


Console.WriteLine(((Struct_Row)MyArrayList[0]).ArrayList_Struct[0]);
SomeFunction(MyArrayList);

Console.WriteLine(((Struct_Row)MyArrayList[0]).ArrayList_Struct[0]);
Console.ReadLine();
}

static void SomeFunction(ArrayList MyArrayList) {
ArrayList NewArrayList = new ArrayList(MyArrayList);

((Struct_Row)NewArrayList[0]).ArrayList_Struct[0] = 3;
}

}
------------------------------------------------------------------------------

Even though I've created a new arraylist in SomeFunction(), when I
change the
value of ArrayList_Struct[0] in SomeFunction(), the change is
reflected in
Main() which I don't want :( Output:


code:------------------------------------------------------------------------------
2
3
------------------------------------------------------------------------------

Yup, it still simply did the copy of all elements in the arraylist. In
this case that is a copy of your struct with a copy of the reference to
the other arraylist....It still points to the original arraylist...thus
the resulting behavior.
So basically my question is, what do I have to do to be able to change
the
values of NewArrayList.ArrayList_Struct in SomeFunction() that will
not
change MyArrayList.ArrayList_Struct in Main() ?

What you want is a Deep Clone. Dotnet supports shallow clones (make a
copy).
If you wish to perform a deep clone, you will have to write the logic
yourself.

Basically you will have to extract the internal Arraylists, clone them
and stick them back in.

As a side note, not really relevant to your issue (yet), why are you
using a struct instead of a class?
Perhaps you attempted the struct for the value semantics. In this case
it was a nice try, and if you only had value types inside the struct it
would have worked. Unfortunately the reference to the ArrayList bit you.

Good luck
Bill
 
M

Marc Gravell

If I understand the code (not so clear), the problem is simply that
you are (when copying the ArrayList into the new ArrayList) cloning
the structure instances. This essentially does a mem-copy, with the
effect that any reference-fields (pointers, in other words) will be
pointing to *the same* underlying object on the managed heap : the
reference-types (classes) do not get cloned with their wrapper. This
means tha((Struct_Row)MyArrayLst[0]).ArrayList_Struct
points to the same arraylist each time. You cannot change this.

Marc
 
?

=?ISO-8859-1?Q?G=F6ran_Andersson?=

An ArrayList can not contain value types, only reference types, so when
you add a value type to the ArrayList, it will be boxed inside an
object, then added to the list.

Furthermore, as your structure contains a reference type, it only
contains a reference to the data. Even if you copy the structure, you
will only make a copy of the reference, the actual data is unchanged.

So, you are two steps from actually copying anything. When you create a
new ArrayList that contains the data from the static ArrayList, you are
only copying the references that point to the objects that contains the
structures, you are not copying the structures.

Let's say that you do copy the actual structures, like this:

ArrayList NewArrayList = new ArrayList()
foreach (object o in MyArrayList) {
Struct_Row row;
row.ArrayList_Struct = (row)o.ArrayList_Struct;
NewArrayList.Add(row);
}

Dispite the fact that you have copied the structures, you have still
only copied the references that the structures contains, not the data
that the references point to. When you use these copied structures, you
will still working with the same ArrayLists that the originals contains.


The value type characteristics of structures will not be useful to you
as long as the structure contains references. Stick to using classes
until you have found something that you can actually use structures for.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top