我有2个来自同一类型的对象,我想浅一个状态到另一个。在C ++中我有memcpy,这很棒。我怎么能在C#中做到这一点? MemberwiseClone()不够好,因为它创建&返回一个新对象,我想复制到现有对象。我想过使用反射,但我担心它对于生产代码来说太慢了。我还想过使用其中一个.Net序列化程序,但我认为它们也可以创建对象而不是设置现有的对象。
我的使用案例
我有一个模板对象(类不是struct),需要通过其中一个实例(由此模板构成的对象)进行更新
有什么想法吗?
答案 0 :(得分:6)
在C#
(以及C++
中),“新对象”和“现有对象的副本”之间没有区别,只要它们的所有成员彼此相等。
假设:
Int32 a = 5;
,两个操作:
Int32 b = 5;
Int32 b = a;
产生相同的结果。
如MSDN reference中所述:
MemberwiseClone方法通过创建新对象,然后将当前对象的非静态字段复制到新对象来创建浅表副本。
如果字段是值类型,则执行字段的逐位复制。
如果字段是引用类型,则复制引用但不引用引用的对象;因此,原始对象及其克隆引用相同的对象。
,即它与memcpy()
C++
完全相同
答案 1 :(得分:4)
[编辑]关于你的澄清: 据我所知,你有N个对象,每个对象都有一个(直接)引用模板对象。您想要回写模板,以便所有对象“看到”这些更改。
建议:imlement a template broker。
class TemplateProvider
{
public MyData Template { get; set; }
}
不是传递模板,而是将模板提供程序传递给对象。
简单地说明组件中的语法,可以添加(私有/内部?)属性
MyData Template { get { return m_templateProvider.Template; } }
void UpdateTemplate() { m_templateProvider.Template =
(MyData) this.MemberwiseClone(); }
模板提供程序还简化了多线程方案中的锁定。
简而言之,除非你亲自去做,否则没办法。但是,如果你无论如何覆盖所有属性,为什么不创建一个新对象?
不支持 memcopy
和类似的低级别构造,因为它们破坏了环境所做的保证。
结构的浅表副本是通过赋值完成的。对于类,MemberwiseClone
是执行此操作的方法 - 但正如您所说,它创建了一个新对象。
没有内置的方法,因为它可能会破坏封装,所以无论如何都应该谨慎使用。
您可以使用反射构建通用例程,但它是否有效取决于类本身。是的,相比之下,ti会很慢。
剩下的是通过自定义界面支持它。您可以提供一个通用的“浅复制”例程来检查接口并使用它,如果没有,则会回退到反射。这使得功能通常可用,并且您可以优化稍后性能的类。
答案 2 :(得分:1)
我猜你可以这样做:
YourObjectType A = new YourObjectType();
YourObjectType B = a.MemberwiseClone();
这将在MemberwiseClone方法中创建一个新对象,使B对象引用它。我猜这符合你的目的。
答案 3 :(得分:1)
为了所有意图和目的,将一个结构分配给另一个结构,在POD对象的C ++中完全就像memcpy
一样。
如果您认为这不适用于您的情况,那么我可以向您保证您的C ++代码不符合标准(即,包含未定义行为形式的错误)。请指定(在问题中)您想要达到的效果。这比用另一种语言复制未定义的行为更有用。
答案 4 :(得分:1)
namespace WindowsFormsApplication7
{
[Serializable] // just put this in your class
class Mate
{
public string SomeProperty { get; set; }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var mA = new Mate();
mA.SomeProperty = "Hey";
var vf = new BinaryFormatter();
var ns = new MemoryStream();
vf.Serialize(ns, mA);
byte[] vytes = ns.ToArray();
var vfx = new BinaryFormatter();
var nsx = new MemoryStream();
nsx.Write(vytes, 0, vytes.Length);
nsx.Seek(0, 0);
var mB = (Mate)vfx.Deserialize(nsx);
mA.SomeProperty = "Yo";
MessageBox.Show(mA.SomeProperty); // Yo
MessageBox.Show(mB.SomeProperty); // Hey
}
}
}
答案 5 :(得分:1)
namespace WindowsFormsApplication7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var dt = new DataTable();
dt.Columns.Add("lastname", typeof(string));
dt.Columns.Add("firstname", typeof(string));
dt.Rows.Add("lennon", "john");
dt.Rows.Add("mccartney", "paul");
var ms = new MemoryStream();
var bf = new BinaryFormatter();
bf.Serialize(ms, dt);
byte[] bytes = ms.ToArray();
var bfx = new BinaryFormatter();
var msx = new MemoryStream();
msx.Write(bytes, 0, bytes.Length);
msx.Seek(0, 0);
// doesn't just copy reference, copy all contents
var dtx = (DataTable)bfx.Deserialize(msx);
dtx.Rows[0]["lastname"] = "Ono";
// just copy reference
var dty = dt;
dty.Rows[0]["lastname"] = "Winston";
MessageBox.Show(dt.Rows[0]["lastname"].ToString()); // Winston
MessageBox.Show(dtx.Rows[0]["lastname"].ToString()); // Ono
MessageBox.Show(dty.Rows[0]["lastname"].ToString()); // Winston
}
}
}
答案 6 :(得分:0)
我无法使用新创建的对象,因为我喜欢根据其中一个实例的状态(即由该模板构成的实例)更改模板对象
答案 7 :(得分:0)
当我考虑它时 - 查看MemberWiseClone()方法实现的代码并了解Microsoft如何解决我的问题非常有趣。
答案 8 :(得分:0)
C# / .Net memcpy 等价物是 Buffer.MemoryCopy .
void MemoryCopy (void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy);
https://docs.microsoft.com/en-us/dotnet/api/system.buffer.memorycopy?view=net-5.0