c# копируют генератор конструктора

Я хочу скопировать значения от одного объекта до другого объекта. Что-то подобное для передачи значением, но с присвоением.

Например:

PushPin newValPushPin = oldPushPin; //I want to break the reference here.

Мне сказали записать конструктору копии для этого. Но этот класс имеет много свойств, вероятно, потребуется час, чтобы записать конструктору копии вручную.

  1. Существует ли лучший способ присвоить объект другому объекту значением?
  2. В противном случае существует ли генератор конструктора копии?

Примечание: ICloneable не доступен в Silverlight.

6
задан Dimitri C. 27 July 2010 в 15:28
поделиться

9 ответов

Если вы можете пометить объект, который должен быть клонирован, как сериализуемый, вы можете использовать сериализацию в памяти для создания копии. Проверьте следующий код, он имеет то преимущество, что он будет работать и с другими типами объектов, и вам не нужно изменять конструктор копирования или копировать код каждый раз, когда свойство добавляется, удаляется или изменяется:

    class Program
    {
        static void Main(string[] args)
        {
            var foo = new Foo(10, "test", new Bar("Detail 1"), new Bar("Detail 2"));

            var clonedFoo = foo.Clone();

            Console.WriteLine("Id {0} Bar count {1}", clonedFoo.Id, clonedFoo.Bars.Count());
        }
    }

    public static class ClonerExtensions
    {
        public static TObject Clone<TObject>(this TObject toClone)
        {
            var formatter = new BinaryFormatter();

            using (var memoryStream = new MemoryStream())
            {
                formatter.Serialize(memoryStream, toClone);

                memoryStream.Position = 0;

                return (TObject) formatter.Deserialize(memoryStream);
            }
        }
    }

    [Serializable]
    public class Foo
    {
        public int Id { get; private set; }

        public string Name { get; private set; }

        public IEnumerable<Bar> Bars { get; private set; }

        public Foo(int id, string name, params Bar[] bars)
        {
            Id = id;
            Name = name;
            Bars = bars;
        }
    }

    [Serializable]
    public class Bar
    {
        public string Detail { get; private set; }

        public Bar(string detail)
        {
            Detail = detail;
        }
    }
6
ответ дан 9 December 2019 в 20:41
поделиться

C # не имеет конструктора копирования . Есть разные способы справиться с этим. На уровне ООП вы можете использовать наследование или агрегацию. AutoMapper тоже стоит попробовать.

1
ответ дан 9 December 2019 в 20:41
поделиться

Если вы хотите копировать при назначении, вы должны использовать структуру вместо класса . Но будьте осторожны, легко сделать небольшие ошибки. Настоятельно рекомендуется, чтобы все элементы были неизменяемыми, чтобы уменьшить вероятность ошибки.

0
ответ дан 9 December 2019 в 20:41
поделиться

Хотя это может не ответить на ваш вопрос напрямую, а добавить цент; обычно термин Clone связан с неглубокой копией (объекты, на которые ссылаются). Чтобы иметь глубокую копию, я полагаю, вам нужно будет изучить некоторый шаблон создания (prototype?). Ответ на этот вопрос может помочь.

0
ответ дан 9 December 2019 в 20:41
поделиться

Вы реализуете метод клонирования объектов Джастина Ангела в Silverlight

с помощью System;

с помощью System. Отражение;

с использованием пространства имен System.Windows;

JustinAngelNet.Silverlight.Framework

{

public static class SilverlightExtensions

{

    public static T Clone<T>(T source)
    {
        T cloned = (T) Activator.CreateInstance(source.GetType());

        foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
        {
            if (curPropInfo.GetGetMethod() != null
                && (curPropInfo.GetSetMethod() != null))
            {
                // Handle Non-indexer properties
                if (curPropInfo.Name != "Item")
                {
                    // get property from source
                    object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});

                    // clone if needed
                    if (getValue != null && getValue is DependencyObject)
                        getValue = Clone((DependencyObject) getValue);

                    // set property on cloned
                    if (getValue != null)
                    curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
                }
                    // handle indexer
                else
                {
                    // get count for indexer
                    int numberofItemInColleciton =
                        (int)
                        curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});

                    // run on indexer
                    for (int i = 0; i < numberofItemInColleciton; i++)
                    {
                        // get item through Indexer
                        object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});

                        // clone if needed
                        if (getValue != null && getValue is DependencyObject)
                            getValue = Clone((DependencyObject) getValue);
                        // add item to collection
                        curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
                    }
                }
            }
        }

        return cloned;
    }
}

}

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

MyClass newObject = SilverlightExtensions.Clone (oldObject);

0
ответ дан 9 December 2019 в 20:41
поделиться

Единственный способ (о котором я знаю) сделать это и сделать это правильно - это реализовать копию самостоятельно. Возьмем, к примеру:

public class FrobAndState
{
  public Frob Frobber { get; set;}
  public bool State { get; set; }
}
public class Frob
{
  public List<int> Values { get; private set; }
  public Frob(int[] values)
  {
    Values = new List<int>(values);
  }
}

В этом примере вам нужно знать , как был реализован Frob, то есть тот факт, что вам нужно вызвать конструктор для создания его копии, поскольку Values ​​доступен только для чтения, чтобы иметь возможность сделать копию данного экземпляра FrobAndState.

Также - вы не могли просто реализовать FrobAndState.Copy таким образом:

public class FrobAndState
{
  // ... Properties

  public FrobAndState Copy()
  {
     var new = new FrobAndState();
     new.State = this.State;
     new.Frobber = this.Frobber;
  }
}

Потому что и экземпляр FrobAndState, который вы вызвали .Copy (), и новый экземпляр, оба будут иметь ссылку на один и тот же экземпляр Frobber.

Короче говоря, копирование сложно , и любую реализацию Copy трудно сделать правильно.

2
ответ дан 9 December 2019 в 20:41
поделиться

Я хочу скопировать значения из одного объекта в другой объект. Нечто похожее на для передачи по значению, но с присваиванием.

Что вы подразумеваете под «с переуступкой»? Если вы имеете в виду, что хотите, чтобы люди могли сказать:

a = b;

И чтобы вы могли определить, что означает = , единственный способ сделать это в C # - это если b будет тип, отличный от a , и вы определили неявное преобразование (или, что более тонко, если a означает что-то вроде xY , где Y - свойство с сеттером). Вы не можете переопределить = для простого назначения между идентичными типами в C #.

Мне сказали написать для этого конструктор копирования . Но у этого класса много свойств , вероятно, потребуется час, чтобы написать конструктор копирования вручную .

Если это действительно правда, то, думаю, у вас другая проблема. Ваш класс слишком велик.

0
ответ дан 9 December 2019 в 20:41
поделиться

Если вы сделаете свой класс Serializable, вы сможете Serialize его в MemoryStream и Deserialize в новый экземпляр.

0
ответ дан 9 December 2019 в 20:41
поделиться

Есть защищенный член под названием «MemberwiseClone», вы можете написать это в своем классе...

public MyClass Clone(){
   return (MyClass)this.MemberwiseClone();
}

, тогда вы можете получить доступ..

MyClass newObject = oldObject.Clone();
3
ответ дан 9 December 2019 в 20:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: