【问题标题】:C# generic extension method for cloning ILists用于克隆 IList 的 C# 通用扩展方法
【发布时间】:2014-04-16 06:39:13
【问题描述】:

我在制作克隆列表的扩展方法时遇到问题。

这个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 错误(不包含“克隆”的定义,并且无法找到接受第一个参数类型为 [...] 的扩展方法“克隆”...)。除非我指定:

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

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

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

【问题讨论】:

  • 为什么要在 List 类本身实现深度克隆时使用泛型方法??
  • 我不明白。您的第一个方法声明为返回IList&lt;T&gt;List&lt;T&gt; 实现IList&lt;T&gt;。有什么问题?
  • 看到这个:Generics: Why can't the compiler infer the type arguments in this case? Eric Lippert 的回答中的关键点是:“你缺少的基本规则可能是约束不是签名的一部分。类型推断是基于签名的。”
  • @Ani,这为我解决了很多问题,谢谢。

标签: c# generics extension-methods


【解决方案1】:

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

注意:

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

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

【讨论】:

  • 这几乎就是我所追求的。我可以转换结果,因为我希望行为模仿 ICloneable 接口的行为。谢谢!
猜你喜欢
  • 1970-01-01
  • 2016-10-30
  • 2015-04-01
  • 2015-10-02
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 2010-12-23
  • 1970-01-01
相关资源
最近更新 更多