Domanda

Ho 2 oggetti dello stesso tipo e vorrei copia superficiale uno stato all'altro. In C ++ ho memcpy che è grande. Come posso farlo in C #? Il MemberwiseClone () non è abbastanza buono perché crea e restituisce un nuovo oggetto e mi piace copiare un oggetto esistente. Ho pensato di utilizzare riflessione, ma ho paura che sarà troppo lento per il codice di produzione. Ho anche pensato di utilizzare uno dei serializzatori NET, ma penso che creano anche oggetto piuttosto che impostare uno esistente.

Il mio caso d'uso:

Ho un oggetto modello (classe non struct), che deve essere aggiornato da uno dei suoi casi (oggetti in questo modello)

Tutte le idee?

È stato utile?

Soluzione

[modifica] riguardo la tua precisazione: Mi pare di capire, si dispone di N oggetti, ognuno ha un riferimento (diretto) per l'oggetto modello. Vuoi scrivere di nuovo al modello in modo che tutti gli oggetti di "vedere" questi cambiamenti.

Suggerimento: imlement un broker template

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

Invece di passare il modello, passare il fornitore di modello per gli oggetti.

per simplyfy la sintassi dei componenti, è possibile aggiungere una proprietà (privato / interno?)

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

Il provider modello semplifica anche il blocco in scenari multithread.


In breve, nessun modo a meno che non lo si fa da soli. Ma perché non creare un nuovo oggetto, se si ignora tutte le proprietà in ogni caso?

memcopy e simili costrutti basso livello non sono supportati dal minano garanzie apportate dall'ambiente.

Una copia poco profonda per le strutture è realizzato mediante cessione. Per le classi, MemberwiseClone è il metodo per farlo - ma come dici tu che crea un nuovo oggetto.

Non v'è alcun costruito in modo per questo, e come si rompe potenzialmente incapsulamento dovrebbe essere usato con cautela in ogni caso.

Si potrebbe costruire una routine generica utilizzando la riflessione, ma se funziona o no dipende dalla classe stessa. E sì, ti sarà comparedly lento.

Ciò che rimane è lo sostengono da un'interfaccia personalizzata. È possibile fornire un routine generica "copia superficiale" che controlla l'interfaccia e la utilizza, e ricade alla riflessione quando non è così. Questo rende le funzionalità disponibili in generale, e si può ottimizzare le classi per le quali le prestazioni conta di seguito.

Altri suggerimenti

In C# (e in C++ troppo), non c'è differenza tra "nuovo oggetto" e "una copia dell'oggetto esistente" finché tutti i loro componenti uguali tra loro.

Data:

Int32 a = 5;

, entrambe le operazioni:

Int32 b = 5;
Int32 b = a;

produrre lo stesso risultato.

Come indicato nel MSDN di riferimento :

  

Il metodo MemberwiseClone Consente di creare una copia con la creazione di un nuovo oggetto, e poi copiare i campi non statici dell'oggetto corrente al nuovo oggetto.

     Se un campo è un tipo di valore, viene eseguita

una copia bit per bit del campo.

     

Se un campo è un tipo di riferimento, il riferimento viene copiato ma l'oggetto di cui non è; Pertanto, l'oggetto originale e il suo clone riferiscono allo stesso oggetto.

, cioè fa esattamente lo stesso come in memcpy() <=>

Credo che si potrebbe solo fare qualcosa di simile:

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

Ciò creerà un nuovo oggetto all'interno del metodo MemberwiseClone un rendere l'oggetto B riferimento esso. Credo che serve i vostri scopi.

L'assegnazione di una struct ad un altro, per tutti gli effetti, funziona esattamente come memcpy in C ++ su oggetti POD.

Se ritieni che questo non si applica nella tua situazione, allora vi posso assicurare che il codice C ++ il vostro non era conforme agli standard (vale a dire, i bug contenuta sotto forma di comportamento non definito). Si prega di specificare ( nella questione ) quale effetto che si vuole raggiungere. Questo sarà più utile che parlare di replicare il comportamento non definito in un'altra lingua.

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

        }
    }
}

Non riesco a usare un oggetto appena creato perché mi piace il modello oggetto da cambiare a seconda dello stato di uno dei suoi casi (cioè esempio in tale modello)

Quando penso a questo proposito - è molto interessante osservare il codice della MemberwiseClone () implementazione del metodo e vedere come Microsoft ha risolto la mia domanda

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top