2017-02-02 2 views
2

Ich wollte eine eingeschränktere Version von MemberwiseClone erstellen, aber realisiert die einzige Möglichkeit, meine eigenen C# -Code Eigenschaften zu einem Objekt hinzufügen können, ist die Verwendung dynamic, aber das kann das Objekt nicht den gleichen Typ wie das Original geben. Meine andere, hässlichere Wahl besteht darin, eine Quelle für den neuen Klon zu senden und sie während der Laufzeit zu kompilieren, die jedoch Komplexitäten enthält. Montageverweise usw., die mir nicht wichtig sind.Wie erstellt MemberWiseClone ein neues Objekt mit den geklonten Eigenschaften?

Für jetzt verwende ich nur MemberwiseClone, aber bin wirklich neugierig, wie es funktioniert. Ich kann keine dekompilierte Quelle finden.

+1

Sie brauchen nicht einen Decompiler für diese Tage. Die [Referenzquelle] (https://referencesource.microsoft.com/#mscorlib/system/object.cs1555d8bb3f97be20) wird Ihnen sagen, dass die Methode von der Laufzeit selbst implementiert wird (MethodImplOptions.InternalCall). Von dort gehst du zum CoreClr Github Repo und suchst nach deinem Anruf. In Ihrem Fall finden Sie schließlich [diese Datei] (https://github.com/dotnet/coreclr/blob/master/src/classlibnative/bcltype/objectnative.cpp), die die Implementierung enthält, an der Sie interessiert sind (ObjectNative: :Klon). – thehennyy

+0

Danke, @thehennyy, ich weiß jetzt mehr darüber, wie man Sachen im Referenzcode findet, aber mein C++ ist ungefähr ein Jahrzehnt hinter mir, und ich weiß nicht, was 'ObjectNative :: Clone' tut. Alles, was ich mit dieser Frage wissen will, ist das Prinzip, mit dem das Objekt geklont wird. Da es C++ ist, macht es ein direktes Byte für das Kopieren von Bytes oder was? – ProfK

+0

Wer in der Welt könnte möglicherweise diese Frage "zu breit" finden und stimmen zu schließen? Ich stelle eine sehr spezifische Frage, die nur sehr begrenzte Antworten haben kann. Der Titel ist die Frage; lese es Dummy. – ProfK

Antwort

8

Es erklärt im Grunde in dem MemberwiseClone MSDN documentation:

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.

Die tatsächliche Implementierung der oben genannten wird intern von CLR implementiert. Sie können als eine optimierte Variante des folgenden Norm C# -Code daran denken:

using System.Reflection; 
using System.Runtime.Serialization; 

public static object CustomMemberwiseClone(object source) 
{ 
    var clone = FormatterServices.GetUninitializedObject(source.GetType()); 
    for (var type = source.GetType(); type != null; type = type.BaseType) 
    { 
     var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); 
     foreach (var field in fields) 
      field.SetValue(clone, field.GetValue(source)); 
    } 
    return clone; 
} 

dh die tatsächliche Art bekommen, eine neue Instanz dieses Typen erstellen, ohne dass Konstruktor Aufruf und jeden Instanz Feldwert aus dem Verzeichnis Quellobjekt.

Wieder ist die tatsächliche interne Implementierung anders (wie in den Kommentaren), das obige Snippet ist nur, um das Prinzip zu demonstrieren und wie Sie eine Methode mit der gleichen Semantik über Reflexion implementieren können (was natürlich viel langsamer sein wird als die CLR-Methode).

HINZUGEFÜGT DURCH DAS OP: Bitte finden Sie unter Iwans Kommentare unten für die weitere Erklärung, die ich suchte. Ich betrachte diesen Teil seiner Antwort und werde ihn basierend darauf akzeptieren.

+0

Danke, ich verstehe, dass ich selbst Code geschrieben habe, um es selbst zu machen, um sicherzustellen, dass nur deklarierte, öffentliche und Nicht-Collection-Eigenschaften und nicht Felder kopiert werden - meine Detailansicht-Modelle sollten nur einfache Eigenschaften haben, aber alles, was ich frage, ist, auf hohem Niveau ausgedrückt, wie macht es die CLR-Methode intern, dh ist es eine binäre Byte für Byte-Kopie, oder was? – ProfK

+1

Verwenden Sie grundsätzlich Low-Level-Kopierspeicher (Bytes). Ähnlich der 'struct' Variablenzuweisung. –

+2

Mit etwas besonderer Sorgfalt auf GC Refs (Zeiger) im Inneren, aber wiederum nichts anderes als zum Beispiel das Kopieren von 'struct' mit' string' darin. Wie auch immer, jetzt sehe ich, dass meine Antwort nicht auf deine Frage eingeht, also werde ich sie löschen. –

Verwandte Themen