Универсальный конструктор копирования C # - PullRequest
18 голосов
/ 12 января 2009

Что было бы лучшим способом написать универсальную функцию конструктора копирования для моих классов c #? Все они наследуются от абстрактного базового класса, чтобы я мог использовать отражение для сопоставления свойств, но мне интересно, есть ли лучший способ?

Ответы [ 5 ]

23 голосов
/ 12 января 2009

Конструктор копирования в основном означает, что у вас есть один параметр - объект, который вы собираетесь скопировать.

Кроме того, сделайте глубокую копию, а не мелкую копию.

Если вы не знаете, что такое глубокие и мелкие копии, то вот вам предложение:

Предположим, вы копируете класс, у которого в поле есть одна строка целых чисел.

Мелкая копия будет:

public class Myclass()
{
    private int[] row;
    public MyClass(MyClass class)
    {
        this.row = class.row
    }
}

Глубокая копия:

public class Myclass()
{
    private int[] row;
    public MyClass(MyClass class)
    {
        for(int i = 0; i<class.row.Length;i++)
        {
            this.row[i] = class.row[i];
        }
    }
}

Глубокая копия действительно получает действительные значения и помещает их в новое поле нового объекта, в то время как поверхностная копия копирует только указатели.

С мелкой копией, если вы установили:

row[3] = 5;

А затем выведите обе строки, обе копии будут иметь 5 как значение 4-го числа. Однако при глубокой копии это будет иметь только первый отпечаток, поскольку строки не имеют одинаковых указателей.

19 голосов
/ 12 января 2009

Избегайте отражения, если можете. Каждый класс должен нести ответственность за копирование своих собственных свойств и отправку его дальше в базовый метод.

14 голосов
/ 12 января 2009

Вы можете создать поверхностную копию эффективно с отражением, предварительно скомпилировав ее, например с Expression. Например, вроде так .

Для глубоких копий сериализация является наиболее надежным подходом.

9 голосов
/ 02 мая 2012

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

public partial class LocationView : Location
{
    public LocationView() {}

    // base class copy constructor
    public LocationView(Location value) {
        Type t = typeof(Location);
        PropertyInfo[] properties = t.GetProperties();
        foreach (PropertyInfo pi in properties)
        {
            pi.SetValue(this, pi.GetValue(value, null), null);
        }
    }
    public Quote Quote { get; set; }
}
0 голосов
/ 30 ноября 2017

Вы можете ссылаться на valueinjecter и более быстрые пакеты nuget и использовать:

public class Myclass()
{
    private string _property;
    public MyClass(MyClass obj)
    {
         this.InjectFrom(obj.DeepClone());
    }
}
...