Micha Wiedenmann
Micha Wiedenmann

Reputation: 20843

How to get a copy of an generic type?

In Hosam Aly's answer to the question "Set/extend List length in C#" this code is proposed:

public static List<T> EnsureSize<T>(this List<T> list, int size, T value)
{
    if (list == null) throw new ArgumentNullException("list");
    if (size < 0) throw new ArgumentOutOfRangeException("size");

    int count = list.Count;
    if (count < size)
    {
        int capacity = list.Capacity;
        if (capacity < size)
            list.Capacity = Math.Max(size, capacity * 2);

        while (count < size)
        {
            list.Add(value);
            ++count;
        }
    }

    return list;
}

where the value is added to the list by reference. How can on ensure the size of a list by using copies instead?

(I tried to use Clone() and ICloneable without success, since some types, e.g. List<T> return a shallow copy and I want a deep copy.)

Upvotes: 1

Views: 91

Answers (1)

nvoigt
nvoigt

Reputation: 77304

As long as you don't know anything about T, whether it's clonable or serializable or a million other ways to copy it, you will have to rely on the caller to provide such means. You want an arbitrary number of new T's, the the simplest version would be to ask for a generator in your method signature:

public static List<T> EnsureSize<T>(this List<T> list, int size, Func<T> generator)
{
    if (list == null) throw new ArgumentNullException("list");
    if (size < 0) throw new ArgumentOutOfRangeException("size");

    int count = list.Count;
    if (count < size)
    {
        int capacity = list.Capacity;
        if (capacity < size)
            list.Capacity = Math.Max(size, capacity * 2);

        while (count < size)
        {
            list.Add(generator());
            ++count;
        }
    }

    return list;
}

Calling it would look like this:

myList.EnsureSize(42, () => new Item());

or this:

myList.EnsureSize(42, () => existingItem.Clone());

or maybe this:

myList.EnsureSize(42, () => StaticItemFactory.CreateNew());

or any other way to construct a new T.

Upvotes: 4

Related Questions