Каким образом return возвращает значение не взаимодействуя с ним?

252
10 февраля 2018, 21:41

Есть следующий метод. Необходим для преобразования идеального дерева в дерево поиска. После всех манипуляций, в последнем условии присваивается результат, но он никак не сохраняется в переменную root. Не смотря на это в отладке я вижу, что root возвращает значение, которое было сохранено в anc.left или anc.right в зависимости от результата. Каким образом это происходит?

    public static Tree AddSearchTree(Tree root, int element)//создание элемента дерева поиска 
    {
        if (root == null)//если дерево пустое 
            return MakePoint(element);
        Tree cur = root;//текущие элемент 
        Tree anc = null;//предок 
        bool ok = false;//флажок 
        while (cur != null && !ok)//пока текущие элемент не null 
        {
            anc = cur;//переходим по элементам 
            if (element == cur.data)
                ok = true;//если значения элементов совпали, не записываем один и тот же 
            else
            {
                if (element < cur.data)//если меньше - в левую ветку 
                    cur = cur.left;
                else
                    cur = cur.right;//если больше - в правую ветку 
            }
        }
        if (ok)
            return root;
        cur = MakePoint(element);
        if (cur.data < anc.data)
            anc.left = cur;
        else
            anc.right = cur;
        return root;
    }
Answer 1

Потому что объекты передаются по ссылке. Когда ты создаешь Tree cur = root, у тебя не копируется сам объект root, а передается лишь ссылка на него. Тем самым и через root, и через cur, у тебя доступ к одной области памяти. Чтоб это избежать, тебе надо сделать конструктор копирования, либо любым другим образом именно скопировать объект со всем его содержимым.

Answer 2

В предыдущем ответ все было правильно сказано. Для более быстрой работы в c# в методы передаются не сами объекты, а их копии.

AddSearchTree(Tree root, int element){...}

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

...
else
            {
                if (element < cur.data)//если меньше - в левую ветку 
                    cur = cur.left;
                else
                    cur = cur.right;//если больше - в правую ветку 
            }
...
cur = MakePoint(element);
        if (cur.data < anc.data)
            anc.left = cur;
        else
            anc.right = cur;

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

В вашем случае можно передавать в метод параметры по ссылке

AddSearchTree(ref Tree root, int element){...}

Или присваивать результат метода к изначальной переменной

...
root = AddSearchTree(Tree root, int element);
...

Здесь более подробно о передаче параметров https://professorweb.ru/my/csharp/charp_theory/level5/5_9.php https://metanit.com/sharp/tutorial/2.9.php

READ ALSO
PageProgress команда в JS

PageProgress команда в JS

Доброго дня!

182
C Sharp форма в другом потоке

C Sharp форма в другом потоке

Здравствуйте! Есть программаВыполняет объемные операции и виснет намертво

225
C# Telegram bot как создать inline кнопку [требует правки]

C# Telegram bot как создать inline кнопку [требует правки]

Как создать url кнопку под сообщением бота?

217
Как узнать что вернуло if

Как узнать что вернуло if

Допустим есть чисто прикладная задача: сортировка пузырьком в трехмерном массиве

195