Вопрос

У меня есть 2 объекта одного типа, и я хотел бы неглубоко скопировать одно состояние в другое.В C++ у меня есть memcpy, и это здорово.Как я могу это сделать на С#?MemberwiseClone() недостаточно хорош, потому что он создает и возвращает новый объект, и мне нравится копировать его в существующий объект.Я думал об использовании отражения, но боюсь, что это будет слишком медленно для производственного кода.Я также думал об использовании одного из сериализаторов .Net, но думаю, что они также создают объект, а не устанавливают существующий.

Мой вариант использования:

У меня есть объект шаблона (класс, а не структура), который необходимо обновить одним из его экземпляров (объекты, созданные на основе этого шаблона).

Есть идеи?

Это было полезно?

Решение

[править] относительно вашего разъяснения:Насколько я понимаю, у вас есть N объектов, каждый из которых имеет (прямую) ссылку на объект шаблона.Вы хотите выполнить обратную запись в шаблон, чтобы все объекты «видели» эти изменения.

Предположение:реализовать брокер шаблонов.

class TemplateProvider
{
   public MyData Template { get; set; }
}

Вместо передачи шаблона передайте объектам поставщика шаблонов.

чтобы упростить синтаксис компонентов, вы можете добавить свойство (частное/внутреннее?)

MyData Template { get { return m_templateProvider.Template; } }
void UpdateTemplate() { m_templateProvider.Template = 
                            (MyData) this.MemberwiseClone(); }

Поставщик шаблонов также упрощает блокировку в многопоточных сценариях.


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

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

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

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

Вы можете создать обобщенную процедуру с использованием отражения, но будет ли она работать или нет, зависит от самого класса.И да, это будет сравнительно медленно.

Осталось поддерживать его с помощью специального интерфейса.Вы можете предоставить общую процедуру «Поверхностного копирования», которая проверяет интерфейс и использует его, а если этого не происходит, возвращается к отражению.Это делает функциональность доступной в целом, и вы можете позже оптимизировать классы, для которых производительность имеет значение.

Другие советы

В C# (И в C++ тоже), нет никакой разницы между «новым объектом» и «копией существующего объекта», если все их члены равны друг другу.

Данный:

Int32 a = 5;

, обе операции:

Int32 b = 5;
Int32 b = a;

дать тот же результат.

Как сказано в Справочник MSDN:

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

Если поле имеет тип значения, выполняется побитовое копирование поля.

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

, т.е.это делает то же самое, что и memcpy() в C++

Я думаю, вы могли бы просто сделать что-то вроде:

YourObjectType A = new YourObjectType();
YourObjectType B = a.MemberwiseClone();

Это создаст новый объект внутри метода MemberwiseClone, и объект B будет ссылаться на него.Думаю, это послужит вашим целям.

Присвоение одной структуры другой практически работает. точно нравиться memcpy в C++ для объектов POD.

Если вы чувствуете, что это неприменимо в вашей ситуации, я могу заверить вас, что ваш код C++ не соответствует стандарту (т. е. содержит ошибки в форме неопределенного поведения).Пожалуйста уточни (в вопросе) какого эффекта вы хотите добиться.Это будет полезнее, чем разговоры о репликации неопределенного поведения на другом языке.

namespace WindowsFormsApplication7
{

    [Serializable] // just put this in your class
    class Mate
    {
        public string SomeProperty { get; set; }
    }

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();


            var mA = new Mate();
            mA.SomeProperty = "Hey";

            var vf = new BinaryFormatter();
            var ns = new MemoryStream();
            vf.Serialize(ns, mA);
            byte[] vytes = ns.ToArray();


            var vfx = new BinaryFormatter();
            var nsx = new MemoryStream();            
            nsx.Write(vytes, 0, vytes.Length);
            nsx.Seek(0, 0);
            var mB = (Mate)vfx.Deserialize(nsx);

            mA.SomeProperty = "Yo";

            MessageBox.Show(mA.SomeProperty); // Yo
            MessageBox.Show(mB.SomeProperty); // Hey
        }
    }
}
namespace WindowsFormsApplication7
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var dt = new DataTable();
            dt.Columns.Add("lastname", typeof(string));
            dt.Columns.Add("firstname", typeof(string));

            dt.Rows.Add("lennon", "john");
            dt.Rows.Add("mccartney", "paul");


            var ms = new MemoryStream();
            var bf = new BinaryFormatter();
            bf.Serialize(ms, dt);
            byte[] bytes = ms.ToArray();



            var bfx = new BinaryFormatter();
            var msx = new MemoryStream();
            msx.Write(bytes, 0, bytes.Length);
            msx.Seek(0, 0);


            // doesn't just copy reference, copy all contents
            var dtx = (DataTable)bfx.Deserialize(msx);


            dtx.Rows[0]["lastname"] = "Ono";


            // just copy reference
            var dty = dt;

            dty.Rows[0]["lastname"] = "Winston";

            MessageBox.Show(dt.Rows[0]["lastname"].ToString()); // Winston
            MessageBox.Show(dtx.Rows[0]["lastname"].ToString()); // Ono
            MessageBox.Show(dty.Rows[0]["lastname"].ToString()); // Winston

        }
    }
}

Я не могу использовать вновь созданный объект, потому что мне нравится шаблон объект, который будет изменен в соответствии с состоянием одного из его экземпляров (т. е. экземпляра, созданного на основе этого шаблона)

Когда я об этом думаю, мне очень интересно взглянуть на код реализации метода MemberWiseClone() и увидеть, как Microsoft решила мой вопрос.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top