Экземпляр объекта из одного класса изменяется из другого класса - PullRequest
1 голос
/ 12 февраля 2020

У меня есть класс FrameSelector , который просто хранит "путь" к фреймам на веб-странице. Этот класс содержит экземпляр FramePath , который является фактическим путем к текущему кадру.

Я создаю экземпляр Элемента , который также содержит поле FramePath, я даю FramePath от FrameSelector до него, когда я использую FrameSelector.SelectDefaultContent (), который по существу очищает FramePath, Element.FramePath имеет 0 сегментов, это не должно быть изменено.

Я предполагаю, что это происходит, потому что Element.FramePath ссылается на FrameSelector .FramePath.

Как мне это преодолеть?

 public class Program   
{
    public static void Run()
    {
        FrameSelector frameSelector = new FrameSelector();

        frameSelector.SelectFrame(0);

        Element el = new Element();
        el.FramePath = frameSelector.FramePath;

        Console.WriteLine(el.FramePath.Segments.Count); // Outputs 1

        frameSelector.SelectDefaultContent(); // Resets frameSelector.FramePath

        Console.WriteLine(el.FramePath.Segments.Count); // Outputs 0? Why? el.FramePath should not have anything to do with frameSelector.FramePath?
        Console.ReadLine();
    }
}

class Element
{
    public FramePath FramePath;
}

class FrameSelector
{
    public FramePath FramePath;

    public FrameSelector()
    {
        FramePath = new FramePath();
    }

    public void SelectFrame(int id)
    {
        FramePath.AddSegment($"(//iframe)[{id + 1}]");
    }

    public void SelectDefaultContent()
    {
        FramePath.Clear();
    }
}

class FramePath
{
    public List<string> Segments { get; private set; }

    public FramePath()
    {
        Segments = new List<string>();
    }

    public void AddSegment(string segment)
    {
        Segments.Add(segment);
    }

    public void RemoveLastSegment()
    {
        Segments.RemoveAt(Segments.Count - 1);
    }

    public void Clear()
    {
        Segments.Clear();
    }
}

Ответы [ 2 ]

1 голос
/ 12 февраля 2020
Element el = new Element();
el.FramePath = frameSelector.FramePath;`

Когда вы присваиваете значение FramePath для el.FramePath, вы по существу устанавливаете два указателя на frameSelector.FramePath. Вы не копируете и не копируете значение объекта, а назначаете другую переменную той же вещи в памяти.

Когда вы вызываете frameSelector.SelectDefaultContent();, вы очищаете FramePath из frameSelector .. но так как el.FramePath также установлен в ту же память el.FramePath также очищается.

Вы можете изучить клонирование или создание Deep Copy (вместо мелкой копии). Это предотвратит изменения других объектов, которые вы хотите использовать для отслеживания старых значений.

Вы можете использовать конструктор new FramePath(frameSelector.FramePath) для создания нового объекта, который поможет в разделении ссылок.

0 голосов
/ 13 февраля 2020

Решено созданием метода Clone.

public FramePath Clone()
    {
        FramePath result = new FramePath();

        result.XpathSegments = XpathSegments.GetRange(0, XpathSegments.Count);

        return result;
    }
...