Изменение объекта с помощью копии все еще вызывает изменение исходного объекта - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть объект облака точек

public interface IPointCloud
{
    void ShiftToOrigin();

    Vertex[] Vertices { get; set; }
}

public class PointCloud : IEquatable<PointCloud>, IPointCloud
{
    public PointCloud(Vertex[] vertices)
    {
        Vertices = vertices;
    }

    // Stuff here.

    public Vertex[] Vertices { get; set; } 
}

, где

public class Vertex : IEquatable<Vertex>
{
    public Vertex() { }
    public Vertex(Vector3 point, Vector3 normal)
    {
        Point = point;
        Normal = normal;
    }
    public Vertex(Vector3 point) : this(point, new Vector3()) { }

    // Stuff here...

    public Vector3 Point; // Note, Vector3 is a struct

    public Vector3 Normal; // Note, Vector3 is a struct
}

Для этого объекта я буду sh выполнять некоторые вычисления, но Я не хочу изменять оригинал . Итак, в методе ниже

public List<LineDescriptor> HoughTansform(IPointCloud pointCloud)
{
    _dX = _settingsProvider.LfdSolverSettings.HoughSpaceStepSize.Value;
    _minimumVotes = _settingsProvider.LfdSolverSettings.HoughMinimumVotesForLineSelection.Value;

    if (pointCloud.Vertices.Length < 2)
        throw new PointCloudException("Point cloud has less than two points");

    // Add more checks once we expose for parameterization. 
    if (_dX < 0)
        throw new ArgumentException("dX cannot be negative");

    if (_minimumVotes < 2)
        _minimumVotes = 2;

    // Ensure we get a shallow copy. 
    PointCloud basePointCloud = new PointCloud(pointCloud.Vertices.ToList().ToArray());
    basePointCloud.ShiftToOrigin();

    // ... More stuff here

я пытаюсь создать новую копию, используя массив Vertex, используя следующую строку

PointCloud basePointCloud = new PointCloud(pointCloud.Vertices.ToList().ToArray());

, но последующие операции на basePointCloud объект модифицирует оригинал.

Как я могу обеспечить правильную чистую копию, чтобы мои изменения в basePointCloud не влияли на pointCloud?

Обратите внимание, я не могу создать глубокую копию, используя любую форму сериализации, так как из-за использования структуры Vector3 мои IPointCloud объекты не сериализуются.

1 Ответ

3 голосов
/ 29 апреля 2020

Vertex является ссылочным типом. Создание копии массива Vertex не создает копию элементов, содержащихся внутри. И исходный массив, и копия будут содержать ссылки на одни и те же Vertex объекты.

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

Другой возможный вариант (чёрт!) - создать механизм копирования в Vertex, который возвращает копию, а затем спроецировать это в новый массив:

new PointCloud(pointCloud.Vertices.Select(v => v.Copy()).ToArray());

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

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