2010-01-14 40 views
7

he¿Copiar una clase a otra?

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

¿Cómo puedo copiar una a otra A? En C++ sé que podría hacer *a1 = *a2;. ¿Hay algo similar en C#? Sé que podría escribir una solución genérica utilizando la reflexión, pero espero que ya exista algo.

Estoy considerando cambiar A a una estructura nullable.

Paso 2 Voy a tener que hacer

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

y copiar los datos de base de B a C.

+1

¿Por qué necesita ¿hacer esto? –

+0

Usted ya ha preguntado esto aquí: http://stackoverflow.com/questions/2067725/best-way-to-convert-a-shared-base – Amy

+0

@yodaj007: Este limpia su idea de esa pregunta. Ya he votado para cerrar el anterior. –

Respuesta

6

Aquí hay un código simple que funciona en cualquier clase, no sólo 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

Suponiendo una es sólo una clase simple, se puede hacer

A newA = instanceOfA.MemberwiseClone(); 

MemberwiseClone() es una copia superficial, así que si su clase se vuelve compleja, con propiedades que también son tipos de referencia, esto no funcionará para usted.

+0

Aunque esto no puede ser tan rápido como un enfoque de no reflexión. –

+0

De acuerdo. Sin embargo, puede ser más conveniente y escalable que un enfoque personalizado. – womp

0

puede clonar, puede definir un constructor de copia. ¿Por qué cambiar la clase a struct solo porque en C++ puedes hacer algo en 10 caracteres? C# es diferente. Las estructuras tienen ventajas y desventajas.

3

Añadir los constructores apropiados:

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

también se debe considerar lo que es inmutable, especialmente si usted está considerando hacer en una estructura. Las estructuras mutables son malvadas.

Finalmente, cuando hereda de una clase, no necesita copiar los miembros de la clase base en la subclase.

+0

+1 si tengo suficientes votos hoy. Inmutable implicaría no tener propiedades establecidas, ¿verdad? –

+0

@lpthnc: 'private set' lo haría. –

+0

Gracias. ¿Cómo declararía eso si quiere seguir publicándose, en la misma línea o por separado? –

7

He utilizado la serialización binaria. Básicamente, serialice la instancia a una secuencia de memoria. Luego, deserialízalo fuera de la corriente de memoria. Tendrás una copia binaria exacta. Será una copia profunda, en lugar de una copia poco profunda.

class a = new ClassA(); 

class b = MySerializationMethod(a); 

Para una copia superficial puede utilizar Object.MemberwiseClone

+0

+1 para este método. Hemos usado esto muchas veces y funciona muy bien. – womp

+0

Parece que Object.MemberwiseClone solo funciona con las dos clases son las mismas y dentro del método de clase? ¿Cómo puedo programar MySerializationMethod? Parece que usaré la reflexión. –

+0

alguien lo publicó a continuación: http://www.c-sharpcorner.com/UploadFile/sd_surajit/cloning05032007012620AM/cloning.aspx sin necesidad de reflexión –

2

Hemos utilizado con éxito este código:

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

Puede haber otros métodos que funcionan mejor, pero tal vez esto le ayudará a

Chris

Cuestiones relacionadas