用于克隆IList的C#泛型扩展方法

时间:2014-04-16 06:39:14

标签: c# generics extension-methods

我无法使用扩展方法来克隆列表。

answer非常接近,提供以下扩展方法:

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

这里的问题是ToList()返回一个List类型的对象,它不一定是我用来调用函数的对象。我希望它返回一个与我称之为Clone的对象类型相同的对象。

我能来的最接近的是:

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;
}

但我一直收到CS1061错误(不包含'Clone'的定义,也没有扩展方法'Clone'接受类型[...]的第一个参数可以找到...)。除非我指明:

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

有没有办法简单地调用没有规格的Clone()?为什么编译器不能推断出我想要的类型?

注意:虽然该示例使用了通用List,但对我来说这对于IList的非List实现也很重要。

1 个答案:

答案 0 :(得分:2)

C#编译器从参数中推断出泛型类型,但方法中没有K类型的参数。

作为替代方法,您可以使用以下方法:

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;
    }
}

请注意:

  • 这可能会在运行时失败(列表类型没有公共无参数构造函数 - 有点不太可能)
  • 您仍然要将结果投射到原始类型

您可能需要考虑使用序列化作为深度克隆对象的替代方法。