我在c#中有一个对象的通用列表,并希望克隆列表。列表中的项是可克隆的,但似乎没有做list. clone()的选项。

有什么简单的办法吗?


当前回答

对于深度克隆,我使用反射如下:

public List<T> CloneList<T>(IEnumerable<T> listToClone) {
    Type listType = listToClone.GetType();
    Type elementType = listType.GetGenericArguments()[0];
    List<T> listCopy = new List<T>();
    foreach (T item in listToClone) {
        object itemCopy = Activator.CreateInstance(elementType);
        foreach (PropertyInfo property in elementType.GetProperties()) {
            elementType.GetProperty(property.Name).SetValue(itemCopy, property.GetValue(item));
        }
        listCopy.Add((T)itemCopy);
    }
    return listCopy;
}

你可以交替使用List或IEnumerable。

其他回答

您可以使用List<T>。ConvertAll(Converter<T, T>)方法创建一个包含原始列表的所有元素的新列表,并使用返回输入值的转换函数。

List<int> originalList = new List<int> { 1, 2, 3, 4, 5 };
List<int> clonedList = new List<int>(originalList.ConvertAll(x => x));

没有必要将类标记为Serializable,在我们的测试中,使用Newtonsoft JsonSerializer甚至比使用BinaryFormatter更快。扩展方法可用于每个对象。

注意:私有成员不克隆

标准的。net JavascriptSerializer选项:

public static T DeepCopy<T>(this T value)
{
    JavaScriptSerializer js = new JavaScriptSerializer();

    string json = js.Serialize(value);

    return js.Deserialize<T>(json);
}

使用Newtonsoft JSON更快的选项:

public static T DeepCopy<T>(this T value)
{
    string json = JsonConvert.SerializeObject(value);

    return JsonConvert.DeserializeObject<T>(json);
}

对于浅拷贝,您可以使用泛型List类的GetRange方法。

List<int> oldList = new List<int>( );
// Populate oldList...

List<int> newList = oldList.GetRange(0, oldList.Count);

引用自:generic Recipes

您还可以使用ToArray简单地将列表转换为数组,然后使用array . clone(…)克隆数组。 根据您的需要,Array类中包含的方法可以满足您的需要。

如果你已经参考了Newtonsoft。Json在你的项目和你的对象是可序列化的,你可以总是使用:

List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))

这可能不是最有效的方法,但除非你做了100次或1000次,否则你甚至不会注意到速度的差异。