Domanda

I am having trouble making an extension method for cloning a list.

This answer is very close, providing the following extension method :

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}

The problem here is that ToList() returns an object of type List which isn't necessarily what I used to call the function with. I would like it to return an object of the same type as the one I called Clone on.

The closest I've been able to come is this :

static private object Clone<T, K>(this T container)
    where T : IList<K>, new()
    where K : ICloneable
{
    T res = new T();

    int size = container.Count;
    for (int i = 0; i < size; ++i)
    {
        K obj = container[i];
        res.Add((K)obj.Clone());
    }

    return res;
}

but I keep getting a CS1061 error (does not contain a definition for 'Clone' and no extension method 'Clone' accepting a first argument of type [...] could be found...). Unless I specify :

List<CloneableType> clone = myList.Clone<List<CloneableType>, CloneableType>();

Is there a way to simply call Clone() without the specifications? Why can't the compiler deduce the types I want?

Note : Although the example uses the generic List, it's important for me that this works for non List implementations of IList as well.

È stato utile?

Soluzione

The C# compiler infers generic types from parameters, but there is no parameter of type K in your method.

As an alternative, you could use the following method:

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone)
         where T : ICloneable
    {
        var list = (IList<T>)Activator.CreateInstance(listToClone.GetType());
        foreach (var item in listToClone)
        {
            list.Add((T)item.Clone());
        }
        return list;
    }
}

Note that:

  • This could fail at runtime (the list type doesn't have a public parameterless constructor - somewhat unlikely)
  • You'd still to cast the result to the original type

You might want to consider using serialization as an alternative method for deep-cloning objects.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top