我想将值从一个对象复制到另一个对象。类似于传递值但具有赋值的东西。
例如:
PushPin newValPushPin = oldPushPin; //I want to break the reference here.
我被告知要为此编写一个复制构造函数。但是这个类有很多属性,手工编写复制构造函数可能需要一个小时。
注意:Silverlight中没有ICloneable。
答案 0 :(得分:6)
如果可以将要克隆的对象标记为Serializable,则可以使用内存中序列化来创建副本。检查以下代码,它的优点是它也适用于其他类型的对象,并且每次添加,删除或更改属性时都不必更改复制构造函数或复制代码:
class Program
{
static void Main(string[] args)
{
var foo = new Foo(10, "test", new Bar("Detail 1"), new Bar("Detail 2"));
var clonedFoo = foo.Clone();
Console.WriteLine("Id {0} Bar count {1}", clonedFoo.Id, clonedFoo.Bars.Count());
}
}
public static class ClonerExtensions
{
public static TObject Clone<TObject>(this TObject toClone)
{
var formatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, toClone);
memoryStream.Position = 0;
return (TObject) formatter.Deserialize(memoryStream);
}
}
}
[Serializable]
public class Foo
{
public int Id { get; private set; }
public string Name { get; private set; }
public IEnumerable<Bar> Bars { get; private set; }
public Foo(int id, string name, params Bar[] bars)
{
Id = id;
Name = name;
Bars = bars;
}
}
[Serializable]
public class Bar
{
public string Detail { get; private set; }
public Bar(string detail)
{
Detail = detail;
}
}
答案 1 :(得分:3)
有一个名为“MemberwiseClone”的受保护成员,您可以在班上写这个......
public MyClass Clone(){
return (MyClass)this.MemberwiseClone();
}
然后你可以访问..
MyClass newObject = oldObject.Clone();
答案 2 :(得分:2)
执行此操作并且正确执行的唯一方法(我知道)是自己实现副本。举个例子:
public class FrobAndState
{
public Frob Frobber { get; set;}
public bool State { get; set; }
}
public class Frob
{
public List<int> Values { get; private set; }
public Frob(int[] values)
{
Values = new List<int>(values);
}
}
在这个例子中,您需要知道 Frob是如何实现的,即您需要调用构造函数来创建它的副本,因为Values是只读的,才能够制作给定FrobAndState实例的副本。
另外 - 你不能只是实现FrobAndState.Copy:
public class FrobAndState
{
// ... Properties
public FrobAndState Copy()
{
var new = new FrobAndState();
new.State = this.State;
new.Frobber = this.Frobber;
}
}
因为您调用.Copy()的FrobAndState实例和新实例都会引用同一个Frobber实例。
简而言之,复制内容是 hard ,任何复制实现都很难做到。
答案 3 :(得分:1)
C# does not have a copy constructor。有不同的方法来解决这个问题。在OOP级别,您可以使用继承或聚合。 AutoMapper也可能值得一试。
答案 4 :(得分:0)
我想从一个对象复制值 到另一个对象。类似的东西 通过值传递但是通过赋值。
“分配”是什么意思?如果你的意思是你希望人们能够说:
a = b;
并且为了定义=
的含义,在C#中唯一可以做到这一点的方法是b
是与a
不同的类型,并且您已经定义了隐式转换(或者更重要的是,如果a
代表x.Y
形式的某些内容,其中Y
是带有setter的属性。对于C#中相同类型之间的简单分配,您无法覆盖=
。
我被告知要写一个复制构造函数 为了这。但这个班级有很多 属性,它可能需要一个 小时写一个拷贝构造函数 手。
如果这是真的,那么我猜你有不同的问题。你的班级太大了。
答案 5 :(得分:0)
如果你上课Serializable
,可以Serialize
将其MemoryStream
和Deserialize
改为新实例。
答案 6 :(得分:0)
如果您想要分配时复制,则应使用struct
代替class
。但要小心,很容易犯下微妙的错误。强烈建议所有结构都是不可改变的,以减少出错的可能性。
答案 7 :(得分:0)
虽然,这可能不会直接回答你的问题,但要增加一分钱;通常,术语Clone
与shallow copy(引用的对象)相关联。要获得深层副本,我相信你需要研究一些创作模式(prototype?)。 this question的答案可能会有所帮助。
答案 8 :(得分:0)
你实现了Justin Angel在Silverlight中克隆对象的方法
使用System;
使用System.Reflection;
使用System.Windows;
命名空间JustinAngelNet.Silverlight.Framework
{
public static class SilverlightExtensions
{
public static T Clone<T>(T source)
{
T cloned = (T) Activator.CreateInstance(source.GetType());
foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
{
if (curPropInfo.GetGetMethod() != null
&& (curPropInfo.GetSetMethod() != null))
{
// Handle Non-indexer properties
if (curPropInfo.Name != "Item")
{
// get property from source
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// set property on cloned
if (getValue != null)
curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
}
// handle indexer
else
{
// get count for indexer
int numberofItemInColleciton =
(int)
curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
// run on indexer
for (int i = 0; i < numberofItemInColleciton; i++)
{
// get item through Indexer
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// add item to collection
curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
}
}
}
}
return cloned;
}
}
}
然后你可以这样做
MyClass newObject = SilverlightExtensions.Clone(oldObject);