Question

J'ai 2 objets du même type et je voudrais copie superficielle d'un état à l'autre. En C ++ j'ai memcpy ce qui est génial. Comment puis-je le faire en C #? Le MemberwiseClone () ne suffit pas bon parce qu'il crée et retourne un nouvel objet et j'aime copier sur un objet existant. Je pensais à l'aide de la réflexion, mais je crains que ce sera trop lent pour le code de production. Je pensais aussi d'utiliser l'un des serializers .Net, mais je pense qu'ils créent également l'objet plutôt que de créer un.

Mon cas d'utilisation:

J'ai un objet modèle (classe non struct) qui doit être mis à jour par l'un de ses instances (objets en ce modèle)

Toutes les idées?

Était-ce utile?

La solution

[modifier] au sujet de votre clarification: Si je comprends bien, vous avez des objets N, chacun a une référence (directe) à l'objet modèle. Vous voulez écrire de nouveau au modèle afin que tous les objets « voir » ces changements.

Suggestion: imlement un courtier de modèle

.
class TemplateProvider
{
   public MyData Template { get; set; }
}

Au lieu de passer le modèle, passez le fournisseur de modèle pour les objets.

pour simplyfy la syntaxe dans les composants, vous pouvez ajouter une propriété (? Privé / interne)

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

Le fournisseur de modèle simplifie également le verrouillage dans des scénarios multithread.


En bref, rien à moins que vous le faites vous-même. Mais pourquoi ne pas créer un nouvel objet si vous substituez toutes les propriétés de toute façon?

memcopy et des constructions à faible niveau similaires ne sont pas pris en charge car elles sapent les garanties apportées par l'environnement.

Une copie peu profonde pour struct est fait par cession. Pour les classes, la méthode est MemberwiseClone de le faire - mais comme vous dites cela crée un nouvel objet.

Il n'y a pas construit de manière à ce que, et comme il se casse potentiellement encapsulation, il doit être utilisé avec soin de toute façon.

Vous pouvez construire une routine générique utilisant la réflexion, mais si cela fonctionne ou non dépend de la classe elle-même. Et oui, ti sera comparedly lente.

Ce qui reste est la soutenir par une interface personnalisée. Vous pouvez fournir une routine « Copier peu profonde » générique qui vérifie l'interface et l'utilise, et retombe à la réflexion quand il ne fonctionne pas. Cela rend généralement disponible la fonctionnalité, et vous pouvez optimiser les classes pour lesquelles la performance est plus tard.

Autres conseils

Dans C# (et aussi C++), il n'y a pas de différence entre le « nouvel objet » et « une copie de l'objet existant » tant que tous leurs membres égaux les uns aux autres.

Vu:

Int32 a = 5;

, les deux opérations:

Int32 b = 5;
Int32 b = a;

donnent le même résultat.

Comme indiqué dans référence MSDN :

  

La méthode MemberwiseClone crée une copie peu profonde en créant un nouvel objet, puis copier les champs non statiques de l'objet courant au nouvel objet.

     

Si un champ est un type de valeur, un bit par bit copie du champ est effectuée.

     

Si un champ est un type de référence, la référence est copié, mais l'objet référencé n'est pas; Par conséquent, l'objet original et son clone se réfèrent au même objet.

, à-dire qu'elle fait exactement la même chose que dans memcpy() <=>

Je suppose que vous pourriez faire quelque chose comme:

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

Cela va créer un nouvel objet dans la méthode MemberwiseClone une rendre l'objet B font référence. Je suppose qu'il sert à vos besoins.

L'attribution d'un struct à l'autre, pour toutes fins utiles, fonctionne exactement comme en C ++ memcpy sur les objets POD.

Si vous pensez que cela ne vaut pas dans votre situation, alors je peux vous assurer que votre code C ++ n'a pas été conforme à la norme (par exemple, contient des bugs sous la forme d'un comportement non défini). S'il vous plaît préciser ( dans la question ) quel effet vous voulez atteindre. Ce sera plus utile que de parler de reproduire un comportement non défini dans une autre langue.

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

        }
    }
}

Je ne peux pas utiliser un objet nouvellement créé parce que j'aime modèle objet à modifier en fonction de l'état d'un de ses instances (i.e. exemple en ce modèle)

Quand je pense à ce sujet - il est très intéressant de regarder le code de la mise en œuvre de la méthode MemberwiseClone () et voir comment Microsoft a résolu ma question

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top