2009-02-04 12 views
7

Ich habe 2 Objekte aus dem gleichen Typ und ich möchte flach einen Zustand auf den anderen kopieren. In C++ habe ich memcpy, was großartig ist. Wie kann ich es in C# machen? Das MemberwiseClone() ist nicht gut genug, weil es erstellt & gibt ein neues Objekt zurück, und ich möchte in ein vorhandenes Objekt kopieren. Ich dachte daran, Reflektionen zu verwenden, aber ich fürchte, es wird zu langsam für den Produktionscode. Ich dachte auch an einen der .Net-Serialisierer, aber ich denke, dass sie auch ein Objekt erstellen, anstatt ein existierendes zu setzen.C# memcpy Äquivalent

My Use Case:

Ich habe ein Template-Objekt (Klasse struct nicht), die von einem seiner Instanzen aktualisiert werden muss (Objekte dieser Vorlage gemacht)

Irgendwelche Ideen?

Antwort

4

[bearbeiten] bezüglich Ihrer Klarstellung: Wie ich verstehe, haben Sie N Objekte, jedes hat einen (direkten) Verweis auf das Vorlagenobjekt. Sie möchten in die Vorlage zurückschreiben, damit alle Objekte diese Änderungen "sehen".

Vorschlag: einen Template-Broker einbinden.

Anstatt die Vorlage zu übergeben, übergeben Sie den Vorlagenanbieter an die Objekte.

um die Syntax in den Komponenten zu vereinfachen, können Sie eine (private/interne?) Eigenschaft

MyData Template { get { return m_templateProvider.Template; } } 
void UpdateTemplate() { m_templateProvider.Template = 
          (MyData) this.MemberwiseClone(); } 

Der Vorlagenanbieter vereinfacht auch das Sperren in Multithread-Szenarien.


Kurz gesagt, auf keinen Fall, wenn Sie es nicht selbst tun. Aber warum nicht ein neues Objekt erstellen, wenn Sie trotzdem alle Eigenschaften überschreiben?

memcopy und ähnliche Low-Level-Konstrukte werden nicht unterstützt, da sie die Garantien der Umgebung untergraben.

Eine flache Kopie für Strukturen wird durch Zuweisung erstellt. Für Klassen ist MemberwiseClone die Methode, um das zu tun - aber wie Sie sagen, dass ein neues Objekt erstellt.

Es gibt keine integrierte Möglichkeit dafür, und da es möglicherweise die Kapselung bricht, sollte es trotzdem vorsichtig verwendet werden.

Sie könnten eine generische Routine mit Reflektion erstellen, aber ob es funktioniert oder nicht, hängt von der Klasse selbst ab. Und ja, ti wird im Vergleich langsam sein.

Was bleibt, ist die Unterstützung durch eine benutzerdefinierte Schnittstelle. Sie können eine generische "Shallow Copy" -Routine bereitstellen, die nach der Schnittstelle sucht und diese verwendet und auf die Reflexion zurückgreift, wenn dies nicht der Fall ist. Dadurch wird die Funktionalität allgemein verfügbar und Sie können die Klassen optimieren, für die die Leistung später von Bedeutung ist.

6

In C# (und in C++ auch), gibt es keinen Unterschied zwischen "neues Objekt" und "eine Kopie des vorhandenen Objekts", solange alle ihre Mitglieder gleich sind.

Gegeben:

Int32 a = 5; 

, beide Operationen:

Int32 b = 5; 
Int32 b = a; 

das gleiche Ergebnis ergeben.

Wie in MSDN reference erklärt:

Die MemberwiseClone-Methode erstellt eine flache Kopie durch ein neues Objekt erstellen, und kopieren Sie dann die nicht-statischen Felder des aktuellen Objekts auf das neue Objekt.

Wenn ein Feld ein Werttyp ist, wird eine bitweise Kopie des Feldes ausgeführt.

Wenn ein Feld ein Referenztyp ist, wird die Referenz kopiert, das referenzierte Objekt jedoch nicht; Daher beziehen sich das ursprüngliche Objekt und sein Klon auf dasselbe Objekt.

, dh es ist genau das gleiche wie memcpy() in C++

1

tut ich denke, man wie etwas tun könnte:

YourObjectType A = new YourObjectType(); 
YourObjectType B = a.MemberwiseClone(); 

Dieses ein neues Objekt in der MemberwiseClone-Methode erstellen wird eine machen die B Objekt Referenz es. Ich schätze, es dient deinen Zwecken.

+0

Er will, wissen, wie man den Inhalt eines Objekts A kopieren * in * ein vorhandenes Objekt B und überschreibt alle Inhalte. MemberwiseClone erstellt ein * neues * Objekt. –

0

Ich kann nicht ein neu erstelltes Objekt verwenden, weil ich die Vorlage Objekt wie nach dem Stand eines seiner Instanzen

+0

Ich würde immer noch eine andere Ebene der Indirektion bevorzugen (z. B. eine "Vorlage Getter"), anstatt ein gemeinsames Objekt zu aktualisieren, aber zugegebenermaßen ist das nahe "nur eine Frage des Geschmacks" – peterchen

0

Wenn ich darüber nachdenke (dh Instanz dieser Vorlage gemacht) geändert werden - es ist sehr interessant, um den Code der MemberWiseClone() Methodenimplementierung zu sehen und zu sehen, wie Microsoft meine Frage gelöst hat.

0

Zuordnung von einer Struktur zu einer anderen, in jeder Hinsicht funktioniert genau wie memcpy in C++ auf POD-Objekte.

Wenn Sie glauben, dass dies in Ihrer Situation nicht zutrifft, kann ich Ihnen versichern, dass Ihr C++ - Code nicht standardkonform war (d. H. Enthaltene Fehler in Form von undefiniertem Verhalten). Bitte geben Sie (in der Frage) an, welchen Effekt Sie erzielen möchten. Dies wird nützlicher sein, als über das Replizieren von undefiniertem Verhalten in einer anderen Sprache zu sprechen.

+0

Bitte beachten Sie meine Bearbeitung in der Frage –

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 
     } 
    } 
} 
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 

     } 
    } 
}