C # memcpy эквивалент - PullRequest
       20

C # memcpy эквивалент

7 голосов
/ 04 февраля 2009

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

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

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

Есть идеи?

Ответы [ 8 ]

6 голосов
/ 04 февраля 2009

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

Дано:

Int32 a = 5;

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

Int32 b = 5;
Int32 b = a;

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

Как указано в Ссылка MSDN :

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

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

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

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

4 голосов
/ 04 февраля 2009

[править] относительно вашего разъяснения: Как я понимаю, у вас есть 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 является методом, который делает это, но, как вы говорите, создает новый объект.

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

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

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

1 голос
/ 04 февраля 2009
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

        }
    }
}
1 голос
/ 04 февраля 2009
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
        }
    }
}
1 голос
/ 04 февраля 2009

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

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

1 голос
/ 04 февраля 2009

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

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

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

0 голосов
/ 04 февраля 2009

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

0 голосов
/ 04 февраля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...