[C#] Cloning a list doesn't create new instances. What else can I try?

Started by
2 comments, last by Spa8nky 14 years ago
If I want to copy the contents of one list to another but not as references to the copied list, how can I do that? I've tried cloning the list:

List<CD_Triangle> triangles = new List<CD_Triangle>(model_Info.Triangles);
and

List<CD_Triangle> triangles = Clone<CD_Triangle>(model_Info.Triangles);

        List<T> Clone<T>(IEnumerable<T> oldList)
        {
            return new List<T>(oldList);
        }

but each time I transform the triangles in the new triangles list it just changes the original lists triangles instead. I guess the new list is just a reference to the old list? Is there a method to copy the list to a new list whose triangles can be altered without affecting the list from which it was copied? Apologies if this post doesn't make sense, I really ought to sleep.
Advertisement
The problem you have is that the List<T> (where T is a reference type) is similar to a list-of-pointers in C/C++. You can add/remove new items in the new list and it won't affect the old list, but if you modify an ITEM in the list, both lists reference the same items.

You could:

- Change the CD_Triangle type from a 'class' to a 'struct'. This is a pretty drastic change, but it's one possibility. (edit) I'm actually not sure if this would work. It might copy the boxed references.

- Give the CD_Triangle type a Clone method, then create a new list by calling that Clone method on every member of the original list. You may be able to alter your generic clone method to call T.Clone, but I'm not sure.
Well, there's a question of whether your Triangle class should actually be a value type, but leaving that aside, you could do something like.

List<T> CopyList<T>(IEnumerable<T> source)   where T : ICloneable{    List<T> copy = new List<T>();    foreach (T t in source)    {        copy.Add((T)t.Clone());    }    return copy;}


This assumes that your Triangle is cloneable. If it isn't you need to provide some way of copying it (parameterised constructor, Copy method or even just allowing the Properties to be set manually.
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Thanks guys.

Quote:
Well, there's a question of whether your Triangle class should actually be a value type


Currently I am importing a model and extracting all the mesh triangles and storing them in a list.

Each time an object is created/spawned using that model, it will require its own copy of the mesh triangles as its transform will be different to the original model transform.

Each time an object is moved, all the triangle vertices that make up the object mesh will have to be transformed by the world transform.

        public Matrix World_Transform        {            get            {                // Should we recreate the world transform? (Has the entity's properties been updated this frame)                if (recreateWorld)                {                    world_Transform =                        Matrix.CreateScale(scale) *                        Matrix.CreateFromQuaternion(orientation);                    world_Transform.Translation = body.Position;                    // Now the world transform has been recreated flag this property as false                    recreateWorld = false;                    for (int i = 0; i < triangles.Count; ++i)                    {                        triangles.Transform(world_Transform);                    }                }                return world_Transform;            }        }


I require all these triangles meshes because decal creation requires clipping to triangle meshes.

Am I approaching this in the correct way or can anyone suggest a better method of dealing with model meshes and triangle transformation?

EDIT:

Memberwise cloning (shallow copy) doesn't work:

                int totalTriangles = model_Info.Triangles.Count;                triangles = new List<CD_Triangle>(totalTriangles);                for (int i = 0; i < totalTriangles; ++i)                {                    triangles.Add(model_Info.Triangles.Clone());                }.....        public CD_Triangle Clone()        {            return (CD_Triangle)this.MemberwiseClone();        }


Quote:
or even just allowing the Properties to be set manually.


Something like this, or is that overkill?

                int totalTriangles = model_Info.Triangles.Count;                triangles = new List<CD_Triangle>(totalTriangles);                for (int i = 0; i < totalTriangles; ++i)                {                    CD_Triangle t = model_Info.Triangles;                    triangles.Add(new CD_Triangle(t.A, t.B, t.C));                }


[Edited by - Spa8nky on April 14, 2010 6:08:13 AM]

This topic is closed to new replies.

Advertisement