Создание копии объекта в С#

Возможный дубликат:
Как вы делаете глубокую копию объекта в .Net(специально для С#)?

Пожалуйста, посмотрите на код ниже (выдержка из книги С#):

namespace Example
{
    class MyClass
    {
        public int val;
    }
    struct myStruct
    {
        public int val;
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyClass objectA = new MyClass();
            MyClass objectB = objectA;
            objectA.val = 10;
            objectB.val = 20;
            myStruct structA = new myStruct();
            myStruct structB = structA;
            structA.val = 30;
            structB.val = 40;
            Console.WriteLine("objectA.val = {0}", objectA.val);
            Console.WriteLine("objectB.val = {0}", objectB.val);
            Console.WriteLine("structA.val = {0}", structA.val);
            Console.WriteLine("structB.val = {0}", structB.val);
            Console.ReadKey();
        }
    }
}

Я понимаю, что он выводит результат ниже

objectA.val = 20
objectA.val = 20
structB.val = 30
structB.val = 40

Последние две строки вывода у меня не проблема, но первые два говорят мне, что objectA и objectB указывают на один и тот же блок памяти (поскольку на С# объекты являются ссылочными типами).

Вопрос заключается в том, как сделать objectB копию objectA, чтобы она указывала на другую область памяти. Я понимаю, что попытки назначить своих членов могут не работать, поскольку эти члены также могут быть ссылками. Итак, как мне сделать objectB совершенно другой объект из objectA?

Спасибо

Ответ 1

Нет встроенного способа. Вы можете использовать MyClass интерфейс IClonable (но он устарел), или просто написать собственный метод копирования/клонирования. В любом случае вам придется написать код.

Для больших объектов вы можете рассмотреть сериализацию + десериализацию (через MemoryStream), чтобы повторно использовать существующий код.

Каким бы ни был метод, тщательно подумайте о том, что означает "копия". Как глубоко он должен идти, есть ли поля идентификаторов, которые будут исключены и т.д.

Ответ 2

Вы можете сделать:

class myClass : ICloneable
{
    public String test;
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

то вы можете сделать

myClass a = new myClass();
myClass b = (myClass)a.Clone();

N.B. MemberwiseClone() Создает неглубокую копию текущего объекта System.Object.

Ответ 3

Самый простой способ сделать это - написать конструктор копирования в классе MyClass.

Что-то вроде этого:

namespace Example
{
    class MyClass
    {
        public int val;

        public MyClass()
        {
        }

        public MyClass(MyClass other)
        {
            val = other.val;
        }
    }
}

Второй конструктор просто принимает параметр своего типа (тот, который вы хотите скопировать) и создает новый объект, назначенный с тем же значением

class Program
{
    static void Main(string[] args)
    {
        MyClass objectA = new MyClass();
        MyClass objectB = new MyClass(objectA);
        objectA.val = 10;
        objectB.val = 20;
        Console.WriteLine("objectA.val = {0}", objectA.val);
        Console.WriteLine("objectB.val = {0}", objectB.val);
        Console.ReadKey();
    }
}

выход:

objectA.val = 10

objectB.val = 20               

Ответ 4

У вас уже есть вопрос об этом, вы могли бы прочитать его

Глубокие объекты клонирования

Нет метода Clone(), который существует в Java, например, но вы можете включить конструктор копирования в свои кланы, что еще один хороший подход.

class A
{
  private int attr

  public int Attr
  {
     get { return attr; }
     set { attr = value }
  }

  public A()
  {
  }

  public A(A p)
  {
     this.attr = p.Attr;
  }  
}

Это будет пример, копирующий член "Attr" при создании нового объекта.