Правильное копирование данных в C # - PullRequest
1 голос
/ 20 января 2011

Я работаю над некоторым кодом моделирования в C #, и у меня есть некоторый код в виде строк:

public void predict(Point start, Point end)
{
    end.velocity = start.velocity + dt * end.acceleration;
    end.position = start.position + dt * end.velocity;
}

Где позиция, скорость, ускорение - это некоторые векторные типы данных, которые я определил с помощью связанных операторов.

А также код, в котором я работаю:

StartPoint = EndPoint;
EndPoint = CurrentPoint;

. * Точки являются экземплярами Точек, которые имеют несколько примитивных (двойных) и не примитивных (векторных) типов данных.

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

Имеется в виду, что если я снова изменю CurrentPoint, я в конечном итоге случайно изменю EndPoint.

В C ++ это просто предотвратить, поскольку я могу определить свой оператор присваивания, чтобы сделать глубокую копию базовых данных в моих объектах Point,Как я могу предотвратить это в C #?

Спасибо за любую помощь!

Редактировать: Класс Vector определяется как

[Serializable]
public class Vector
{
    private Double[] data = new Double[Constants.Dimensions];

    ... snip ...

    public static Vector operator +(Vector lhs, Vector rhs)
    {
        Vector result = new Vector();
        for (UInt32 i = 0; i < Constants.dimensions; i++)
            result[i] = lhs[i] + rhs[i];
        return result;
    }

    lots more code here 
}

Ответы [ 3 ]

2 голосов
/ 20 января 2011

Это одна из самых неприятных проблем с дизайном C #, IMHO.

Если 'Point' является структурой (значением), то будет сделана копия для каждого элемента, поэтому x = y создаст независимая копия г.Но если это класс (ссылка), x = y просто укажет ссылку x на то же хранилище, которое используется для y, поэтому эти два просто станут разными «псевдонимами» для одних и тех же данных.

ДваРешения, которые я знаю для вашей проблемы:

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

  • Используйте класс, но будьте очень и очень осторожны при использовании =, чтобы убедиться, что высохранить независимую копию данных.Вам нужно изменить x = y на что-то другое, например, x = new Point(y);.

0 голосов
/ 20 января 2011

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

Для перехода по ссылке сделайте следующее:

public void predict(ref Point start, ref Point end)
{
    end.velocity = start.velocity + dt * end.acceleration;
    end.position = start.position + dt * end.velocity;
}

Затем вам нужно будет вызвать метод с ключевым словом ref следующим образом:

predict(ref start, ref end);
0 голосов
/ 20 января 2011

Не могли бы вы использовать Clone (), а затем реализовать глубокое копирование, как вам нужно?

StartPoint = EndPoint; 
EndPoint = (Point)CurrentPoint.Clone(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...