c#拷贝构造函数生成器
我想将一个对象的值复制到另一个对象。类似于通过价值传递但具有分配的东西。c#拷贝构造函数生成器
例如:
PushPin newValPushPin = oldPushPin; //I want to break the reference here.
有人告诉我,写这个拷贝构造函数。但是这个类有很多属性,可能需要一个小时才能手动编写一个拷贝构造函数。
- 有没有更好的方法来按值分配一个对象到另一个对象?
- 如果不是,是否有复制构造函数生成器?
注意:ICloneable在Silverlight中不可用。
如果您可以将要克隆的对象标记为可序列化,那么您可以使用内存中序列化来创建副本。请检查以下代码,它的优点是它也可以用于其他类型的对象,并且每次添加,删除或更改属性时都不必更改复制构造函数或代码复制:
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;
}
}
这通常不起作用,因为可能会引用不应该被复制的对象。手工完成是唯一正确的方法(因为这可以让你定义复制的真正含义)。如果课程足够大,这是一个真正的问题,他们太大了。 – 2010-03-26 10:57:23
@Donal - 更不用说可能会引用不可序列化的类。也就是说,如果OP可以完全控制正在复制的类,从而序列化,那么对于它们来说,这绝对是一个适当的解决方案。 – Rob 2010-03-26 11:03:58
让我们看看...用Silverlight标记,所以可能会得到一些对不受控制的类实例的引用。手动复制更好(编写自定义序列化器是另一种选择,但这比复制更困难)。 – 2010-03-26 22:33:23
要做到这一点,并且正确地做到这一点,唯一的方法就是自己实现副本。举个例子:
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是如何实现的,即你需要调用构造函数是只读的创建一个副本作为价值的事实,能够复制给定的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的同一个实例。
总之,复制东西是硬和任何复制实现是很难得到正确的。
我想从一个对象 复制到另一个对象的值。类似的东西 传递值,但与分配。
你是什么意思的“与转让”?如果你的意思是你希望人们能够说:
a = b;
如果b
是一个不同类型a
和你”你界定什么=
手段,你可以做,在C#中是唯一的出路我们定义了一个隐式转换(或者更简单的说,如果a
代表x.Y
的形式,其中Y
是一个包含setter的属性)。您不能覆盖=
以获取C#中相同类型之间的简单分配。
我被告知要为此写一个拷贝构造函数 。但是这个类有很多 属性,它可能需要 小时才能通过 手写一个拷贝构造函数。
如果那是真的,那么我会猜测你有一个不同的问题。你的班级太大了。
如果你让你的班级Serializable
你可以Serialize
到MemoryStream
和Deserialize
到一个新的实例。
如果你想复制作业,你应该使用struct
而不是class
。但要小心,容易犯下微妙的错误。强烈建议所有的工作人员尽量减少出错的机会。
有一个称为保护成员 “MemberwiseClone”,你可以在你的类写这个...
public MyClass Clone(){
return (MyClass)this.MemberwiseClone();
}
,那么你可以访问..
MyClass newObject = oldObject.Clone();
虽然,这可能不是回答你的问题直接,但增加一分;通常术语Clone
与shallow copy(被引用的对象)相关联。要获得深层副本,我相信您需要查看一些创建模式(prototype?)。 this question的答案可能会有所帮助。
您实现了Justin Angel在Silverlight中克隆对象的方法
using System;
using System.Reflection;
using 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);
@Brian,手写复制构造函数耗时过长的原因是我需要为主类(** PushPin **)使用的其他类编写复制构造函数。 – 2010-03-26 09:11:11