1

I'm struggling to clone a list of lists of a reference type. I tried to implement ICloneable in my reference class, however, it don't seems to call the Clone() method in it.

Code:

public class Solid : ICloneable{

    private double[,] _points;  //vertices do solido
    private int[,] _edges;  //arestas do solido
    public int[,] Faces { get; private set; }   //faces do solido

    public int[,] Edges {
        get { return _edges; }
        set { _edges = value; }

    }
    ...

    public object Clone() {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();

        bf.Serialize(ms, this);

        ms.Position = 0;
        object obj = bf.Deserialize(ms);
        ms.Close();
        return obj;
    }
}
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
FrankTominc
  • 119
  • 1
  • 10
  • Could you show us the `Clone` implementation? – Mathias R. Jessen Feb 09 '16 at 00:23
  • Edited with the code @MathiasR.Jessen – FrankTominc Feb 09 '16 at 00:27
  • Why do you want to clone such a structure in the first place? There is probably a better way to do what you want to do. Say what problem you are really trying to solve. – Eric Lippert Feb 09 '16 at 00:41
  • @EricLippert it's a school project for computer graphics. I have a list of solids that can be grouped, hence the list of lists. There is two types of projections, if I use the original list to make the perspective projection I'll screw up with the parallel projection, so, I think I need to copy it and make two different lists for the two types of projection. – FrankTominc Feb 09 '16 at 00:51
  • 2
    This sounds like a job for another data structure. I would make a flat list of solids and then construct the group using a group-by query. Construct the projections with projection queries. Queries do not mutate the underlying collection, and they can easily be turned into lists if for some reason you need to. – Eric Lippert Feb 09 '16 at 00:53
  • I don't have experience with queries. The deadline is pretty close, so I've choosen the data structure I was more familiarized with. – FrankTominc Feb 09 '16 at 00:57

2 Answers2

5

With LINQ, you can do something like this:

public List<List<T>> Clone<T>(List<List<T>> original) where T : ICloneable
{
    return original
        .Select(sl => sl.Select(x => (T)x.Clone()).ToList())
        .ToList();
}
Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
4

You have a List<List<T>>, where T is ICloneable.

Obviously for each T you just call Clone() to get an object (which you can turn into a T by casting back), but to get a clone of the nested list you need something like:

public static List<List<T>> Clone<T>(List<List<T>> original)
    where T : ICloneable
{
    var result = new List<List<T>>();
    foreach ( List<T> innerList in original )
    {
        var innerResult = new List<T>();
        foreach ( T item in innerList )
        {
            var clone = (T)item.Clone();
            innerResult.Add(clone);
        }

        result.Add(innerResult);
    }

    return result;
}

This will ensure that Clone() is called on each T, and the lists (outer and nested) are separate instances to the original.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92