Jef*_*tes 483
如果您的元素是值类型,那么您可以这样做:
List<YourType> newList = new List<YourType>(oldList);
Run Code Online (Sandbox Code Playgroud)
但是,如果它们是引用类型并且您需要深层复制(假设您的元素正确实现ICloneable
),您可以执行以下操作:
List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);
oldList.ForEach((item) =>
{
newList.Add((ICloneable)item.Clone());
});
Run Code Online (Sandbox Code Playgroud)
显然,替换ICloneable
上面的泛型并使用你实现的元素类型进行强制转换ICloneable
.
如果您的元素类型不支持ICloneable
但具有复制构造函数,则可以执行以下操作:
List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);
oldList.ForEach((item)=>
{
newList.Add(new YourType(item));
});
Run Code Online (Sandbox Code Playgroud)
就个人而言,我会避免ICloneable
因为需要保证所有成员的深层副本.相反,我建议复制构造函数或类似的工厂方法YourType.CopyFrom(YourType itemToCopy)
返回一个新的实例YourType
.
任何这些选项都可以通过方法(扩展名或其他方式)进行包装.
小智 363
您可以使用扩展方法.
static class Extensions
{
public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
{
return listToClone.Select(item => (T)item.Clone()).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
Ant*_*tts 80
对于浅表副本,您可以改为使用泛型List类的GetRange方法.
List<int> oldList = new List<int>( );
// Populate oldList...
List<int> newList = oldList.GetRange(0, oldList.Count);
Run Code Online (Sandbox Code Playgroud)
引自:仿制食谱
Pat*_*ins 78
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;
}
Run Code Online (Sandbox Code Playgroud)
这是使用C#和.NET 2.0实现此目的的一种方法.你的对象需要[Serializable()]
.目标是丢失所有引用并构建新引用.
小智 22
稍作修改后你也可以克隆:
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;
}
Run Code Online (Sandbox Code Playgroud)
Xav*_*ohn 22
要克隆列表,只需调用.ToList()
Microsoft (R) Roslyn C# Compiler version 2.3.2.62116
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> var x = new List<int>() { 3, 4 };
> var y = x.ToList();
> x.Add(5)
> x
List<int>(3) { 3, 4, 5 }
> y
List<int>(2) { 3, 4 }
>
Run Code Online (Sandbox Code Playgroud)
Jad*_*ijo 16
除非您需要对您内部的每个对象进行实际克隆,否则List<T>
克隆列表的最佳方法是使用旧列表作为集合参数创建新列表.
List<T> myList = ...;
List<T> cloneOfMyList = new List<T>(myList);
Run Code Online (Sandbox Code Playgroud)
myList
插入或删除等更改不会影响cloneOfMyList
,反之亦然.
但是,两个列表包含的实际对象仍然相同.
Jam*_*ran 14
如果你只关心价值类型......
你知道的类型:
List<int> newList = new List<int>(oldList);
Run Code Online (Sandbox Code Playgroud)
如果您之前不知道类型,则需要辅助函数:
List<T> Clone<T>(IEnumerable<T> oldList)
{
return newList = new List<T>(oldList);
}
Run Code Online (Sandbox Code Playgroud)
正义:
List<string> myNewList = Clone(myOldList);
Run Code Online (Sandbox Code Playgroud)
Der*_*ang 13
使用AutoMapper(或您喜欢的任何映射库)进行克隆非常简单且易于维护.
定义您的映射:
Mapper.CreateMap<YourType, YourType>();
Run Code Online (Sandbox Code Playgroud)
做魔术:
YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);
Run Code Online (Sandbox Code Playgroud)
Pro*_*rod 10
如果您已在项目中引用了Newtonsoft.Json,并且您的对象可序列化,则可以始终使用:
List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))
Run Code Online (Sandbox Code Playgroud)
可能不是最有效的方法,但除非你做1000次,否则你可能甚至没有注意到速度差异.
对于深层复制,ICloneable 是正确的解决方案,但这里有一个与 ICloneable 类似的方法,使用构造函数而不是 ICloneable 接口。
public class Student
{
public Student(Student student)
{
FirstName = student.FirstName;
LastName = student.LastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
// wherever you have the list
List<Student> students;
// and then where you want to make a copy
List<Student> copy = students.Select(s => new Student(s)).ToList();
Run Code Online (Sandbox Code Playgroud)
您将需要以下库来制作副本
using System.Linq
Run Code Online (Sandbox Code Playgroud)
您还可以使用 for 循环代替 System.Linq,但 Linq 使其变得简洁明了。同样,您可以按照其他答案的建议进行操作并制定扩展方法等,但这些都不是必要的。
无需将类标记为可序列化,在我们的测试中,使用 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);
}
Run Code Online (Sandbox Code Playgroud)
使用Newtonsoft JSON 的更快选项:
public static T DeepCopy<T>(this T value)
{
string json = JsonConvert.SerializeObject(value);
return JsonConvert.DeserializeObject<T>(json);
}
Run Code Online (Sandbox Code Playgroud)
如果有人读过这篇文章,我会很幸运......但为了不在我的 Clone 方法中返回类型对象列表,我创建了一个接口:
public interface IMyCloneable<T>
{
T Clone();
}
Run Code Online (Sandbox Code Playgroud)
然后我指定了扩展名:
public static List<T> Clone<T>(this List<T> listToClone) where T : IMyCloneable<T>
{
return listToClone.Select(item => (T)item.Clone()).ToList();
}
Run Code Online (Sandbox Code Playgroud)
这是我的 A/V 标记软件中的接口实现。我想让我的 Clone() 方法返回 VidMark 列表(而 ICloneable 接口希望我的方法返回对象列表):
public class VidMark : IMyCloneable<VidMark>
{
public long Beg { get; set; }
public long End { get; set; }
public string Desc { get; set; }
public int Rank { get; set; } = 0;
public VidMark Clone()
{
return (VidMark)this.MemberwiseClone();
}
}
Run Code Online (Sandbox Code Playgroud)
最后,在类中使用扩展:
private List<VidMark> _VidMarks;
private List<VidMark> _UndoVidMarks;
//Other methods instantiate and fill the lists
private void SetUndoVidMarks()
{
_UndoVidMarks = _VidMarks.Clone();
}
Run Code Online (Sandbox Code Playgroud)
有人喜欢吗?有什么改进吗?