我有一个表示一些数据的类和一个集合类(从CollectionBase派生)。当我将一个集合类的实例分配给另一个时,它是通过引用分配的,所以我实现了ICloneable
接口。
public void Add(object item)
{
InnerList.Add(item);
}
public object Clone()
{
MyCollection clone = new MyCollection();
foreach (MyClass item in this)
{
clone.Add(item);
}
return clone;
}
现在一切正常。但是当我浏览元素并将它们逐个添加到克隆实例时,为什么不通过引用添加它们呢? Add
方法如何将它添加到InnerList?为什么不通过引用添加?如果我添加这个集合的一个实例,让我们说List
并更改列表中的元素怎么办?原始实例是否会被更改?
修改:这是MyClass
。
public class MyClass
{
public bool IsEnabled { get; set; }
public string Parent { get; set; }
public string Child { get; set; }
public MyClass()
{
IsEnabled = false;
Parent = string.Empty;
Child = string.Empty;
}
public MyClass(bool isEnabled, string parent, string child)
{
IsEnabled = isEnabled;
Parent = parent;
Child = child;
}
public bool IsValid()
{
return (!Parent.Equals(string.Empty) &&
!Child.Equals(string.Empty));
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (!obj.GetType().IsAssignableFrom(this.GetType()))
{
return false;
}
return ((MyClass)obj).Parent.Equals(Parent) ||
((MyClass)obj).Child.Equals(Child);
}
public bool Equals(MyClass myClass)
{
if (myClass == null)
{
return false;
}
return myClass.Parent.Equals(Parent) ||
myClass.Child.Equals(Child);
}
public override int GetHashCode()
{
return Parent.GetHashCode();
}
}
编辑2:我做的是
MyClass item = new MyClass(true, "test", "test");
MyCollection collection = new MyCollection();
collection.Add(item);
MyCollection newCollection = new MyCollection();
newCollection = (MyCollection) collection.Clone();
newCollection[0].Parent = "changed";
现在在此之后我预计集合[0] .Parent也将被更改为“已更改”,但它仍然保持不变。是不是通过引用克隆实例添加了它?
答案 0 :(得分:1)
如果集合中的项目是引用类型,则会通过引用添加它们。如果您添加了克隆集合的内容,则不会修改原始集合。
答案 1 :(得分:1)
这取决于您希望如何实现克隆方法。如果要返回对象的浅表副本,则可以使用Object.MemberwiseClone
方法。如果要返回深层副本,则可以使用BinaryFormatter
序列化和反序列化对象/集合。这将返回一个新的对象/集合。
答案 2 :(得分:0)
[Serializable]
class CustomClass
{
int _id;
string _value;
public CustomClass(int id, string value)
{
_id = id;
_value = value;
}
}
[Serializable]
class CustomClassCollection
{
private IList<CustomClass> _list = null;
public CustomClassCollection()
{
_list = new List<CustomClass>();
}
public void Add(CustomClass a)
{
_list.Add(a);
}
}
public static class ObjectCopier
{
public static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
使用它像:
CustomClassCollection a = new CustomClassCollection();
CustomClassCollection b = ObjectCopier.Clone<CustomClassCollection>(a);
a.Add(new CustomClass(1, "A"));
a.Add(new CustomClass(2, "B"));
a.Add(new CustomClass(3, "C"));
b.Add(new CustomClass(1, "A"));
b.Add(new CustomClass(2, "B"));