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, оно будет нулевым. Не уверен в причине.
В Assign()
root
— это параметр, который скрывает участника с таким же именем. Вы назначаете новый экземпляр параметру, который выходит за рамки при выходе из метода.
имена аргументов, совпадающие с полями, раздражают мои глаза, как фак
@GregK. Рискуя, что нечистый дух Чарльза Симони будет преследовать меня всю вечность, я почти жалею, что не было обычного префикса параметра C#, аналогичного _
для приватных полей.
@EdPlunkett Я не могу не подчеркнуть, насколько невероятно полезно это соглашение. Также прописные имена для свойств класса.
Вы должны назначить «новый дочерний класс (данные)» текущему корню экземпляра. Для этого вам нужно присвоить новый объект "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). Так будет понятнее и читать.
@Senthil Переименование параметра не поможет, хотя оно должен делает характер проблемы более понятным для вас: вы назначаете новый экземпляр параметру, который является локальным для метода. Вы все еще выбрасываете новый экземпляр. Вы передаете this.root
в AssignRec()
, но внутри метода параметр rootnode
— это просто новая ссылка на то, что вы передали. Изменение его значения не изменит значение this.root
.
Если бы вы могли сообщить мне об обновленном коде, который был бы полезен.
Нам нужно быть осторожными, когда у нас есть точно такое же имя для аргумента, как и для поля, потому что внутри метода имя будет ссылаться на аргумент, если мы не укажем поле с помощью 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;
}
Возможно, вам следует сообщить нам, что вы хотите, чтобы метод делал, поскольку ваше редактирование делает желаемый результат еще более неясным (поскольку вы сейчас ничего не назначаете полю класса). Какова цель метода?
Я пытался понять, почему передача this.root в методе Assign не сохраняет значение, которое обновляется в методе AssignRec.
Хорошо, я думаю, это потому, что вы ничего не присваиваете this.root
(вы присваиваете имя аргумента, которое ничего не делает). Этот ответ устраняет эту проблему. Но что вы хотите, чтобы он делал, если аргумент root
равен нетnull
?
Я пытался понять только первое задание.
Обновляется ли изменение значения в AssignRec в корне? Почему мы должны присваивать обратно значение.
Код в этом ответе говорит: назначьте поле нашего класса this.root
аргументу root
, который был передан в этот метод, если это значение не равно нулю, и в этом случае назначьте ему новый экземпляр ChildClass
, используя предоставленный data
.
если бы вы могли сообщить мне об изменениях в новом коде, это помогло бы
Я понимаю код, который вы предоставили, но я пытался понять, почему мой код не сохраняет значение в дочернем классе.
Это то, что я сказал в своем первом предложении, и как вы продемонстрировали в своем обновленном коде. Вы ничего не назначаетеroot
. Вы только меняете назначение переменной аргумент, которая отбрасывается в конце вызова метода. Не уверен, какую часть вы не понимаете, или почему вы думаете, что root
изменится в вашем текущем коде.
Если я правильно понимаю, даже если мы передаем this.root в AssignRec, он обрабатывается как локальная переменная метода (rootnode/root), и любые изменения считаются локальными. Чтобы получить назначение, его необходимо назначить обратно в корень объекта. Я ожидал, что ссылка на объект должна автоматически обновляться внутри метода. Но прямо сейчас я ясно. Спасибо за это.
Да, аргумент root
начинается с указания на поле root
. Но когда вы переназначаете его, теперь он указывает на новый экземпляр ChildClass
. Однако root
поле никогда не меняется. Думайте о ссылочных типах как об указателях на ячейку памяти. Однако если вы хотите сделать что-то вроде rootArgument.data = someNewData
, то вы являются влияете на данные поля root
, поскольку rootArgument
указывает на то же место, что и поле root
.
Версия моего кода немного сбивает с толку, но многим будет интересно узнать, почему она не работает.
Где код, который пытается получить к нему доступ и получает null?