Как реализовать метод клонирования и копирования внутри класса? - PullRequest
13 голосов
/ 11 ноября 2010

У меня есть класс с именем Employee с 3 свойствами, которые называются ID, Name, Dept. Мне нужно реализовать метод Copy и Clone? Когда я использую метод Copy или Clone, мне нужно избегать кастинга? как я это сделаю?

пример: такой же как DataTable, который имеет DataTable.Copy() и DataTable.Clone().

Ответы [ 6 ]

14 голосов
/ 11 ноября 2010

Вам необходимо реализовать интерфейс IClonable и обеспечить реализацию для метода клонирования. Не реализовывайте это, если хотите избежать приведения.

Простой метод глубокого клонирования может заключаться в сериализацииобъект в память, а затем десериализовать его.Все пользовательские типы данных, используемые в вашем классе, должны быть сериализуемыми с помощью атрибута [Serializable].Для клонирования вы можете использовать что-то вроде

  public MyClass Clone()
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();

        bf.Serialize(ms, this);

        ms.Position = 0;
        object obj = bf.Deserialize(ms);
        ms.Close();

        return obj as MyClass;
    }

Если ваш класс имеет только типов значений , то вы можете использовать конструктор копирования или просто присвоить значенияновый объект в методе Clone.

3 голосов
/ 11 ноября 2010

Вы имеете в виду, как реализовать ICloneable.Clone () и заставить его возвращать тип самого класса.

public class MyType : ICloneable
{
  public MyType Clone() //called directly on MyType, returns MyType
  {
    return new MyType(/* class-dependant stuff goes here */);
  }
  object ICloneable.Clone() // called through ICloneable interface, returns object
  {
    return Clone();
  }
}
3 голосов
/ 11 ноября 2010

Вам нужно использовать интерфейс ICloneable или этого достаточно, если у вас просто есть два метода с именем Clone и Copy, которые определены в универсальном интерфейсе?

public class YourClass : ICloneable<YourClass>
{
    // Constructor logic should be here
    public YourClass Copy() { return this; }        
    public YourClass Clone() { return new YourClass(ID, Name, Dept); }
}

interface  IClonable<T>
{
    T Copy();
    T Clone();
}

Или я что-то не так понял?

Что я пытаюсь сказать, так это то, что вам не нужно делать это более сложным, чем оно есть? Если вам нужно, чтобы ваши объекты соответствовали кому-то, вы можете написать его самостоятельно, если тот, который указан в .Net Framework, слишком сложен для данной ситуации. Вы также должны определить разницу с Clone и Copy, то есть, что они значат для вас? Я знаю, что есть несколько сайтов, которые указывают, что Clone это глубокая копия, а Copy это мелкая копия.

2 голосов
/ 26 августа 2013

Вот пример:

namespace XXX
{
     [Serializable]
    public class ItemChecklist : ICloneable
    {

       // [...here properties, attributes, etc....]



        object ICloneable.Clone()
        {
            return this.Clone();
        }
        public ItemChecklist Clone()
        {
            return (ItemChecklist)this.MemberwiseClone();
        }


    }
}

Т.е. если вы используете эту функцию, в "itemAdd" у вас будет полная копия объекта "itemTemp" со всеми его значениями.

ItemChecklist itemAdd = itemTemp.Clone();
2 голосов
/ 15 ноября 2010

Я часто вижу конструкторы копирования, предлагаемые в качестве альтернативы методу клонирования, но, за исключением закрытых классов, поведение очень отличается.Если у меня есть тип Car, который просто поддерживает свойства VIN, BodyColor и BodyStyle, и производный тип FancyCar, который также поддерживает InteriorFabric и SoundSystem, то код, который принимает объект типа Car и использует конструктор копирования Car для его дублирования, завершится.с машиной.Если FancyCar передается в такой код, получающийся в результате «дубликат» будет новым автомобилем, который имеет VIN, BodyColor и BodyStyle, которые соответствуют оригинальному автомобилю, но у которых не будет никакого InteriorFabric или SoundSystem.Напротив, код должен был принимать Car и использовать на нем метод клонирования, передача FancyCar в код приведет к созданию FancyCar.

Если кто-либо не хочет использовать Reflection, любой метод клонирования долженего база включает в себя вызов base.MemberwiseClone.Поскольку MemberwiseClone не является виртуальным методом, я бы предложил определить метод защищенного виртуального клонирования;Вы также можете запретить дочерним классам вызывать MemberwiseClone, определив фиктивный вложенный класс защищенной области с тем же именем (поэтому, если дочерний класс пытается вызвать base.MemberwiseClone, он не будет интерпретироваться как бессмысленная ссылка нафиктивный класс).

2 голосов
/ 11 ноября 2010

Проверьте этот объект клонирования с использованием IL в C # http://whizzodev.blogspot.com/2008/03/object-cloning-using-il-in-c.html

...