2010-01-14 11 views
7

hoCopia una classe in un'altra?

class A 
{ 
    public int a; 
    public string b; 
} 

come posso copiare A ad un altro A? In C++ so che potrei fare *a1 = *a2;. C'è qualcosa di simile in C#? So che potrei scrivere una soluzione generica usando il riflesso ma spero che esista già qualcosa.

Sto considerando di cambiare A in una struttura nullable.

Fase 2 avrò bisogno di fare

class B : A {} 
class C : A {} 

e copiare i dati di base da B a C.

+1

Perché è necessario Fai questo? –

+0

L'hai già chiesto qui: http://stackoverflow.com/questions/2067725/best-way-to-convert-a-shared-base – Amy

+0

@ yodaj007: Questo ripulisce la sua idea da quella domanda. Ho già votato per chiudere il vecchio. –

risposta

6

Ecco qualche semplice codice che funziona su qualsiasi classe, e non solo base.

public static void DuckCopyShallow(this Object dst, object src) 
    { 
     var srcT = src.GetType(); 
     var dstT= dst.GetType(); 
     foreach(var f in srcT.GetFields()) 
     { 
      var dstF = dstT.GetField(f.Name); 
      if (dstF == null) 
       continue; 
      dstF.SetValue(dst, f.GetValue(src)); 
     } 

     foreach (var f in srcT.GetProperties()) 
     { 
      var dstF = dstT.GetProperty(f.Name); 
      if (dstF == null) 
       continue; 

      dstF.SetValue(dst, f.GetValue(src, null), null); 
     } 
    } 
4

assumendo una è solo una semplice classe, si può fare

A newA = instanceOfA.MemberwiseClone(); 

MemberwiseClone() è una copia superficiale, quindi, se la tua classe diventa complessa, con proprietà che sono anche tipi di riferimento, questo non funzionerà per te.

+0

Anche se questo non può essere veloce come un approccio non di riflessione. –

+0

concordato. Tuttavia, può essere più comodo e scalabile rispetto a un approccio personalizzato. – womp

0

è possibile clonare, è possibile definire un costruttore di copia. Perché cambiare classe per strutturare solo perché in C++ puoi fare qualcosa in 10 caratteri. C# è diverso. Le strutture hanno vantaggi e svantaggi.

3

Aggiungi costruttori appropriate:

class Foo 
{ 
    public Foo(int a, string b) 
    { 
     A = a; 
     B = b; 
    } 

    public Foo(Foo other) 
    { 
     A = other.A; 
     B = other.B; 
    } 

    public int A { get; set; } 
    public string B { get; set; } 
} 

si dovrebbe anche considerare che lo rende immutabile, soprattutto se state pensando di farne una struct. Le strutture mutevoli sono malvagie.

Infine, quando si eredita da una classe, non è necessario copiare i membri dalla classe base nella sottoclasse.

+0

+1 se ho avuto abbastanza voti oggi. Immutabile non implicherebbe proprietà fisse, giusto? –

+0

@lpthnc: 'set privato' lo farebbe. –

+0

Grazie. Come dichiareresti che se vuoi continuare ad essere pubblico - sulla stessa linea o separatamente? –

7

Ho usato la serializzazione binaria. In pratica, serializza l'istanza in un flusso di memoria. Quindi, deserializzare dal flusso di memoria. Avrai una copia binaria esatta. Sarà una copia profonda, piuttosto che una copia superficiale.

class a = new ClassA(); 

class b = MySerializationMethod(a); 

Per una copia è possibile utilizzare Object.MemberwiseClone

+0

+1 per questo metodo. L'abbiamo usato molte volte e funziona benissimo. – womp

+0

Sembra che Object.MemberwiseClone funzioni solo con le due classi uguali e all'interno del metodo di classe? Come potrei programmare MySerializationMethod? Sembra che userò la riflessione. –

+0

qualcuno l'ha postato qui sotto: http://www.c-sharpcorner.com/UploadFile/sd_surajit/cloning05032007012620AM/cloning.aspx nessuna riflessione necessaria –

2

Abbiamo utilizzato questo codice con successo:

using System; 
using System.IO; 
using System.Runtime.Serialization.Formatters.Binary; 

namespace Utility { 
    internal static class ObjectCloner { 
     public static T Clone<T>(T obj) { 
      using (MemoryStream buffer = new MemoryStream()) { 
       BinaryFormatter formatter = new BinaryFormatter(); 
       formatter.Serialize(buffer, obj); 
       buffer.Position = 0; 
       T temp = (T)formatter.Deserialize(buffer); 
       return temp; 
      } 
     } 
    } 
} 

Ci possono essere altri metodi che funzionano meglio, ma forse questo ti aiuterà a

Chris

Problemi correlati