如何在 C# 中克隆通用列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/222598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I clone a generic list in C#?
提问by Fiona
I have a generic list of objects in C#, and wish to clone the list. The items within the list are cloneable, but there doesn't seem to be an option to do list.Clone()
.
我在 C# 中有一个通用的对象列表,并希望克隆该列表。列表中的项目是可克隆的,但似乎没有选项 do list.Clone()
。
Is there an easy way around this?
有没有简单的方法来解决这个问题?
采纳答案by ajm
You can use an 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();
}
}
回答by Anthony Potts
For a shallow copy, you can instead use the GetRange method of the generic List class.
对于浅拷贝,您可以改用泛型 List 类的 GetRange 方法。
List<int> oldList = new List<int>( );
// Populate oldList...
List<int> newList = oldList.GetRange(0, oldList.Count);
Quoted from: Generics Recipes
引自:泛型食谱
回答by Jeff Yates
If your elements are value types, then you can just do:
如果您的元素是值类型,那么您可以这样做:
List<YourType> newList = new List<YourType>(oldList);
However, if they are reference types and you want a deep copy (assuming your elements properly implement ICloneable
), you could do something like this:
但是,如果它们是引用类型并且您想要深层复制(假设您的元素正确实现ICloneable
),则可以执行以下操作:
List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);
oldList.ForEach((item) =>
{
newList.Add((ICloneable)item.Clone());
});
Obviously, replace ICloneable
in the above generics and cast with whatever your element type is that implements ICloneable
.
显然,替换ICloneable
上面的泛型并使用实现ICloneable
.
If your element type doesn't support ICloneable
but does have a copy-constructor, you could do this instead:
如果您的元素类型不支持ICloneable
但确实有一个复制构造函数,您可以这样做:
List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);
oldList.ForEach((item)=>
{
newList.Add(new YourType(item));
});
Personally, I would avoid ICloneable
because of the need to guarantee a deep copy of all members. Instead, I'd suggest the copy-constructor or a factory method like YourType.CopyFrom(YourType itemToCopy)
that returns a new instance of YourType
.
就个人而言,我会避免,ICloneable
因为需要保证所有成员的深层副本。相反,我建议使用复制构造函数或类似的工厂方法YourType.CopyFrom(YourType itemToCopy)
返回YourType
.
Any of these options could be wrapped by a method (extension or otherwise).
这些选项中的任何一个都可以由方法(扩展或其他)包装。
回答by James Curran
If you only care about value types...
如果您只关心值类型...
And you know the type:
你知道类型:
List<int> newList = new List<int>(oldList);
If you don't know the type before, you'll need a helper function:
如果您之前不知道类型,则需要一个辅助函数:
List<T> Clone<T>(IEnumerable<T> oldList)
{
return newList = new List<T>(oldList);
}
The just:
刚刚:
List<string> myNewList = Clone(myOldList);
回答by Patrick Desjardins
public static object DeepClone(object obj)
{
object objResult = null;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, obj);
ms.Position = 0;
objResult = bf.Deserialize(ms);
}
return objResult;
}
This is one way to do it with C# and .NET 2.0. Your object requires to be [Serializable()]
. The goal is to lose all references and build new ones.
这是使用 C# 和 .NET 2.0 实现的一种方法。您的对象需要是[Serializable()]
. 目标是丢失所有引用并构建新引用。
回答by pratik
public static Object CloneType(Object objtype)
{
Object lstfinal = new Object();
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
binaryFormatter.Serialize(memStream, objtype); memStream.Seek(0, SeekOrigin.Begin);
lstfinal = binaryFormatter.Deserialize(memStream);
}
return lstfinal;
}
回答by Ajith
After a slight modification you can also clone:
稍作修改后,您还可以克隆:
public static T DeepClone<T>(T obj)
{
T objResult;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, obj);
ms.Position = 0;
objResult = (T)bf.Deserialize(ms);
}
return objResult;
}
回答by Peter
public class CloneableList<T> : List<T>, ICloneable where T : ICloneable
{
public object Clone()
{
var clone = new List<T>();
ForEach(item => clone.Add((T)item.Clone()));
return clone;
}
}
回答by Derek Liang
Use AutoMapper (or whatever mapping lib you prefer) to clone is simple and a lot maintainable.
使用 AutoMapper(或您喜欢的任何映射库)进行克隆非常简单且易于维护。
Define your mapping:
定义您的映射:
Mapper.CreateMap<YourType, YourType>();
Do the magic:
施展魔法:
YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);
回答by Furkan Kat?
You can use extension method:
您可以使用扩展方法:
namespace extension
{
public class ext
{
public static List<double> clone(this List<double> t)
{
List<double> kop = new List<double>();
int x;
for (x = 0; x < t.Count; x++)
{
kop.Add(t[x]);
}
return kop;
}
};
}
You can clone all objects by using their value type members for example, consider this class:
例如,您可以使用它们的值类型成员克隆所有对象,考虑这个类:
public class matrix
{
public List<List<double>> mat;
public int rows,cols;
public matrix clone()
{
// create new object
matrix copy = new matrix();
// firstly I can directly copy rows and cols because they are value types
copy.rows = this.rows;
copy.cols = this.cols;
// but now I can no t directly copy mat because it is not value type so
int x;
// I assume I have clone method for List<double>
for(x=0;x<this.mat.count;x++)
{
copy.mat.Add(this.mat[x].clone());
}
// then mat is cloned
return copy; // and copy of original is returned
}
};
Note: if you do any change on copy (or clone) it will not affect the original object.
注意:如果您对复制(或克隆)进行任何更改,它不会影响原始对象。