Ссылка на объект для дочернего класса

namespace Test
{
    public class Program
    {
        static void Main(string[] args)
        {
            TestClass testC = new TestClass();
            testC.AssignRec(10);
            //testC.root - this is null 
        }
    }

    public class TestClass
    {
        public Childclass root;
        public void Assign(int data)
        {
           AssigRec(this.root,data);
        }
        public void AssignRec(Childclass rootnode, int data)
        {
            if (rootnode == null)
            {
                rootnode = new Childclass(data);
            }
        }
    }

    public class Childclass
    {
        public int data;
        public Childclass(int data)
        {
            this.data = data;
        }
    }
}

Обновлено имя дочернего параметра. Присвоение значения для подкласса ChildClass внутри TestClass, но после присвоения, и если я попытаюсь получить доступ к значению Childcalss, оно будет нулевым. Не уверен в причине.

Где код, который пытается получить к нему доступ и получает null?

Blorgbeard 28.05.2019 21:23

В Assign()root — это параметр, который скрывает участника с таким же именем. Вы назначаете новый экземпляр параметру, который выходит за рамки при выходе из метода.

15ee8f99-57ff-4f92-890c-b56153 28.05.2019 21:23

имена аргументов, совпадающие с полями, раздражают мои глаза, как фак

Greg K. 28.05.2019 21:24

@GregK. Рискуя, что нечистый дух Чарльза Симони будет преследовать меня всю вечность, я почти жалею, что не было обычного префикса параметра C#, аналогичного _ для приватных полей.

15ee8f99-57ff-4f92-890c-b56153 28.05.2019 21:25

@EdPlunkett Я не могу не подчеркнуть, насколько невероятно полезно это соглашение. Также прописные имена для свойств класса.

Greg K. 28.05.2019 21:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
5
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы должны назначить «новый дочерний класс (данные)» текущему корню экземпляра. Для этого вам нужно присвоить новый объект "this.root". Внесите изменения в TestClass, как показано ниже:

    public class TestClass
    {
        public Childclass root;

        public void Assign(Childclass root, int data)
        {
            if (root == null)
            {
                //over here
                this.root = new Childclass(data);
            }
        }
    }

@Senthil, вы должны назначить новый объект ChildClass члену данных TestClass «root». Однако в вашем коде вы назначаете новый объект параметру. Либо используйте this.root, как в ответе, ИЛИ вы можете просто изменить имя свойства на Root (заглавная R). Так будет понятнее и читать.

Rishabh Kumar 28.05.2019 21:42

@Senthil Переименование параметра не поможет, хотя оно должен делает характер проблемы более понятным для вас: вы назначаете новый экземпляр параметру, который является локальным для метода. Вы все еще выбрасываете новый экземпляр. Вы передаете this.root в AssignRec(), но внутри метода параметр rootnode — это просто новая ссылка на то, что вы передали. Изменение его значения не изменит значение this.root.

15ee8f99-57ff-4f92-890c-b56153 28.05.2019 21:47

Если бы вы могли сообщить мне об обновленном коде, который был бы полезен.

Senthil 28.05.2019 22:17
Ответ принят как подходящий

Нам нужно быть осторожными, когда у нас есть точно такое же имя для аргумента, как и для поля, потому что внутри метода имя будет ссылаться на аргумент, если мы не укажем поле с помощью this.root.

Итак, код присваивает поле класса rootтолько если аргументrootявляетсяnull.

Вместо этого кажется, что вы хотите выполнить задание, если вспомогательное поле равно null, и в этом случае вы должны сделать что-то вроде:

    public void AssignRec(Childclass root, int data)
    {
        // Assign the field 'root' to the argument passed to this method unless the argument
        // to this method is 'null', in which case assign a new instance of ChildClass
        this.root = root ?? new ChildClass(data);
    }

Хотя как потребитель этого класса я был бы немного сбит с толку, если бы я вызвал метод Assign и передал какой-то data, и ничего не произошло (что и произошло бы, если бы поле класса root не было null).

Меня также смутил бы метод, который принимает оба ChildClassа такжеdata, поскольку неясно, какова связь между этими аргументами.

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

public void Assign(int data)
{
    if (this.root == null)
    {
        this.root = new ChildClass(data);
    }
    else
    {
        this.root.data = data;
    }
}

public void Assign(ChildClass root)
{
    this.root = root;
}

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

Rufus L 28.05.2019 21:49

Я пытался понять, почему передача this.root в методе Assign не сохраняет значение, которое обновляется в методе AssignRec.

Senthil 28.05.2019 21:53

Хорошо, я думаю, это потому, что вы ничего не присваиваете this.root (вы присваиваете имя аргумента, которое ничего не делает). Этот ответ устраняет эту проблему. Но что вы хотите, чтобы он делал, если аргумент root равен нетnull?

Rufus L 28.05.2019 21:54

Я пытался понять только первое задание.

Senthil 28.05.2019 21:56

Обновляется ли изменение значения в AssignRec в корне? Почему мы должны присваивать обратно значение.

Senthil 28.05.2019 21:58

Код в этом ответе говорит: назначьте поле нашего класса this.root аргументу root, который был передан в этот метод, если это значение не равно нулю, и в этом случае назначьте ему новый экземпляр ChildClass, используя предоставленный data.

Rufus L 28.05.2019 21:59

если бы вы могли сообщить мне об изменениях в новом коде, это помогло бы

Senthil 28.05.2019 22:02

Я понимаю код, который вы предоставили, но я пытался понять, почему мой код не сохраняет значение в дочернем классе.

Senthil 28.05.2019 22:10

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

Rufus L 28.05.2019 22:20

Если я правильно понимаю, даже если мы передаем this.root в AssignRec, он обрабатывается как локальная переменная метода (rootnode/root), и любые изменения считаются локальными. Чтобы получить назначение, его необходимо назначить обратно в корень объекта. Я ожидал, что ссылка на объект должна автоматически обновляться внутри метода. Но прямо сейчас я ясно. Спасибо за это.

Senthil 28.05.2019 22:40

Да, аргумент root начинается с указания на поле root. Но когда вы переназначаете его, теперь он указывает на новый экземпляр ChildClass. Однако rootполе никогда не меняется. Думайте о ссылочных типах как об указателях на ячейку памяти. Однако если вы хотите сделать что-то вроде rootArgument.data = someNewData, то вы являются влияете на данные поля root, поскольку rootArgument указывает на то же место, что и поле root.

Rufus L 28.05.2019 22:42

Версия моего кода немного сбивает с толку, но многим будет интересно узнать, почему она не работает.

Senthil 28.05.2019 22:52

Другие вопросы по теме