我在集合中有一个接受IEnumerable的构造函数。我想使用项目枚举和创建新集合,但不引用相同的项目。项目可以是值和参考类型:
CustomCollection cc = new CustomCollection (IEnumerable<T> items)
{
foreach (var item in items)
{
this.Add(item); // justs adds the reference for ref types.
}
}
编辑:.NET集合具有相同的方法,并且不执行深层复制。为什么你想要一个引用与原始元素相同元素的集合?
答案 0 :(得分:3)
如果有问题的类支持序列化,您可以将集合序列化为临时流,并将它们反序列化为新集合。
有些类支持ICloneable,但其确切的功能由程序员决定。它可能是一个深层拷贝,也可能不是。
当然,并非所有类都支持序列化或克隆,因此您无法对所有类型进行操作。
您需要为此设置一些限制。
答案 1 :(得分:2)
如果对象是可序列化的,您可以制作如下的深层副本:
private object GetCopy(object original)
{
if (original == null)
{
return null;
}
object result;
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, original);
stream.Position = 0;
result = formatter.Deserialize(stream);
stream.Close();
}
return result;
}
答案 2 :(得分:0)
我认为如果您的项目支持ICloneable接口(正确实现接口函数),您将能够调用创建深层副本的.clone函数。
答案 3 :(得分:0)
执行深层复制的效果差别很大,这就是CLR不会自动提供深层复制的原因。例如,想象一下,如果您的深层副本复制了对象,这些对象包含操作系统管理的资源(如SQL连接,套接字,自定义GDI画笔等),那么会发生什么。
你真的需要坚持使用上面建议的方法。如果您认为您信任源以正确实现接口,请检查T是否为ICloneable。如果不是(信任源或T不可克隆),则检查对象是否标记为ISerializable或具有SerializableAttribute,然后序列化/反序列化为新对象。
如果T不可复制或可序列化,那么您可能应该抛出异常而不是尝试进行深层复制。
答案 4 :(得分:-2)
你做不到。并非所有对象都支持类似克隆的方法。
答案 5 :(得分:-2)
我不知道语法,因为我没有使用它很多,但是这可能不会用Reflection完成吗?我意识到反射通常会导致性能损失,但您可能会做一些切换案例的事情,如下所示:
(伪代码)
if(item.isValueType) {
newCol.Add(item)
} elseif(item.isRefType && item.SupportsICloneable) {
newCol.Add(item.clone())
} else {
doReflectionCopy()
}
您还可以为可序列化检查添加代码,并包含Frederik的方法。