Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/18: Рейтинг темы: голосов - 18, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 17.04.2018
Сообщений: 236
1

Изменение полей объекта в методе

22.04.2018, 11:46. Показов 3273. Ответов 10
Метки нет (Все метки)

Объясните, пожалуйста подробно почему при обычном взятии объекта в качестве аргумента не происходит изменение го поля только при взятии с ref?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Test(int i) { a = i;
}
// При выполнении этого метода аргумент не будет изменен.
public void noChange([COLOR="seagreen"][COLOR="seagreen"]Test о[/COLOR][/COLOR]) {
Test newob = new Test(0);
о = newob; // Выполнение данного оператора не оказывает влияния на объект
// "о" вне метода noChange(). }
/*почему не оказывает влияния на обьект ведь была принята переменная (ссылка) типа Test и ей была присвоена другая ссылка. Или была создана копия аргумента о ссылочного типа, которому присвоена новая ссылка (но внутри привоенного обьекта ничего изменяться не будет) и аргумент о будет удалён по завершении выполнения метода?*/
// После выполнения этого метода переменная "о" будет ссылаться на другой
// объект. public void change([COLOR="SeaGreen"]ref Test о[/COLOR]) {
Test newob = new Test(0); о = newob; // Этот оператор изменит аргумент. }
}
class CallObjByRef { public static void Main() {
Test ob = new Test(100);
Console.WriteLine("Значение переменной ob.a после инициализации объекта: "
+ ob.а);
ob.noChange(ob);
Console.WriteLine("Значение переменной ob.a после вызова метода " +
"noChange(): " + ob.a);
ob.change(ref ob); //обьект ob может изменять сам себя (принимать в аргумент)
Console.WriteLine("Значение переменной оb.а после вызова метода " +
"change(): " + ob.a); }
}


Ниже представлен результат выполнения этой программы.
Значение переменной ob.a после инициализации объекта: 100
Значение переменной ob.a после вызова метода noChange(): 100
Значение переменной ob.a после вызова метода change(): 0
В этой программе переменной о присваивается ссылка на новый объект внутри метода noChange(), что не влияет на объект ob внутри метода Main(). Однако внутри метода change(), в котором используется параметр с модификатором ref, присвоение переменной о ссылки на новый объект приводит к тому, что внутри метода Main() переменная ob будет ссылаться уже на другой объект.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2018, 11:46
Ответы с готовыми решениями:

Изменение значений полей объекта через их имена
Возможно ли изменить значение НЕСТАТИЧЕСКОГО поля ОБЪЕКТА. Так, чтобы поле было получено через имя.

Несколько полей в методе ADO find
Синтаксис вида recset.find 'field1='xxx' and field2='www'' выдает ошибку, неужели в ADO в методе...

Создание объекта в const методе
Есть код:void OrderPart::_printDocument(const QString &filename) const { QPrintDialog *dialog...

Использование переменной в методе COM объекта
Есть SQL-подобная база, доступ к базе возможен только через COM интерфейс. Реализован следующий...

__________________

Записывайтесь на профессиональные курсы С#-разработчиков‌
10
29 / 31 / 27
Регистрация: 15.11.2017
Сообщений: 121
22.04.2018, 17:14 2
Цитата Сообщение от Ivanjs Посмотреть сообщение
почему при обычном взятии объекта в качестве аргумента не происходит изменение го поля
Потому что вы работаете с копией этого объекта.
0
1 / 1 / 0
Регистрация: 17.04.2018
Сообщений: 236
22.04.2018, 20:53  [ТС] 3
Копия ведь создаётся когда мы берём аргумент по значению, а объект можно взять только по ссылке
0
186 / 164 / 100
Регистрация: 14.03.2018
Сообщений: 426
22.04.2018, 21:09 4
Ivanjs, экземпляр класса передаётся по ссылке, но сама ссылка передаётся по значению (копируется), то есть присвоение ссылке нового значения внутри метода не оказывает никакого влияния вне этого метода, т.к. работа происходит с копией ссылки на объект. Но если использовать ref, то в метод передаётся ссылка на ссылку на объект (аналог ** в С++) и вот тогда уже возможно изменить ссылку, указывающую на объект.
1
Эксперт .NET
14870 / 11257 / 2950
Регистрация: 17.09.2011
Сообщений: 18,846
23.04.2018, 07:08 5
Цитата Сообщение от Ivanjs Посмотреть сообщение
почему при обычном взятии объекта в качестве аргумента не происходит изменение го поля только при взятии с ref?
Твердо запомните два простых правила:
1. При передаче переменной в метод и при присваивании ее другой переменной, всегда создается копия этой переменной, если не указано обратное через модификаторы ref/in/out. При наличии этих модификаторов создается "псевдоним" для используемой переменной: вы можете обращаться к одной и той же переменной по разным именам.
2. В переменных значимых типов хранятся экземпляры, а в переменных ссылочных типов — ссылки на экземпляры.

В дальнейшем при возникновении подобных вопросов просто применяйте эти два правила и сразу станет понятно что происходит.
0
1 / 1 / 0
Регистрация: 17.04.2018
Сообщений: 236
23.04.2018, 08:50  [ТС] 6
Мне не ясно следующее, вот пример где создаётся копия ссылки на объект,
Vehicle car1 = new Vehicle();
Vehicle car2 = car1;

car1.mpg=26;

оба оператора WriteLine() выведут одинаковое значение — 26.

Console.WriteLine(car1.mpg);
Console.WriteLine(car2.mpg);

здесь car2 ссылается на ту же область памяти, что и car1 хотя это её копия. Т. е. изменение копии повлечёт изменение оригинала, т. к. обе ссылаются на один объект.


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

Но, выше сказано что ссылка берётся по значению, значение переменной ссылочного типа это адресс в памяти (в данном случае адресс 1-го объекта), т. е. копируется адресс аргумента ссылочного типа и присваивается параметру ф-ии это должно означать что теперь параметр (в данном случае о) ссылается на тот же объект, что и аргумент ф-ии, тогда при изменение параметра должен быть изменён и объект на который он ссылается т. е. первоначальный объект.
0
Эксперт .NET
14870 / 11257 / 2950
Регистрация: 17.09.2011
Сообщений: 18,846
23.04.2018, 08:57 7
Цитата Сообщение от Ivanjs Посмотреть сообщение
здесь car2 ссылается на ту же область памяти, что и car1 хотя это её копия. Т. е. изменение копии повлечёт изменение оригинала, т. к. обе ссылаются на один объект.
Верно.

Цитата Сообщение от Ivanjs Посмотреть сообщение
Однако, в данном случае поскольку не изменяется значение поля аргумента, то видимо выделяется память под второй объект т. е. копия ссылки ссылается на другой адресс в памяти или на другой объект.
Верно.

Цитата Сообщение от Ivanjs Посмотреть сообщение
Но, выше сказано что ссылка берётся по значению, значение переменной ссылочного типа это адресс в памяти (в данном случае адресс 1-го объекта), т. е. копируется адресс аргумента ссылочного типа и присваивается параметру ф-ии
А вот тут уже не верно — смотрите выше про копирование переменной.

Конкретно смущает вот эта фраза:
Цитата Сообщение от Ivanjs Посмотреть сообщение
копируется адресс аргумента ссылочного типа
Почему вы решили, что копируется адрес аргумента, а не его значение?
Особенно учитывая, что вы сами же упоминаете это:
Цитата Сообщение от Ivanjs Посмотреть сообщение
выше сказано что ссылка берётся по значению
Как у вас "ссылка берется по значению" трансформировалось в "копируется адрес аргумента"?
Аргумент — это значение, которое передается в метод. В данном случае это значение — ссылка на объект. Копируется значение, а не адрес этого значения, т.е. адрес места, в котором это значение хранится.
0
1 / 1 / 0
Регистрация: 17.04.2018
Сообщений: 236
23.04.2018, 09:04  [ТС] 8
согласен, ошибочка копия не адресса аргумента а значение т. е. адресса области памяти на которую ссылался аргумет

Добавлено через 2 минуты
но собственно это и не ясно
0
Эксперт .NET
14870 / 11257 / 2950
Регистрация: 17.09.2011
Сообщений: 18,846
23.04.2018, 09:15 9
Цитата Сообщение от Ivanjs Посмотреть сообщение
т. е. адресса области памяти на которую ссылался аргумет
Опять мимо.
Откуда у вас берутся эти "адреса области памяти"?
Переменная — это локация в памяти.
В этой локации может храниться какое-нибудь значение.
В переменных ссылочных типов значение — ссылка на экземпляр объекта.
При копировании переменной копируется значение, в ней хранящееся. Значение, а не адрес этой переменной в памяти.
При присваивании одной переменной другой, производится копирование переменной.
Параметр метода — это переменная.
При указании переменной в качестве аргумента при вызове метода, параметру вызываемого метода присваивается значение передаваемой переменной. Значение. Не адрес в памяти, где эта переменная хранится, а значение, которое записано в этой памяти.
В результате у вас две переменные, находящиеся в разных местах в памяти, но имеющие одинаковые значения: ссылку на объект.
Если вы измените значение одной переменной, то это никак не повлияет на значение другой переменной, потому что обе переменных находятся в разных, независимых друг от друга местах.

Давайте приведу аналогию с файловой системой.
Файл — это переменная.
Файлы бывают двух видов: значимые (обычные файлы с данными) и ссылочные (ярлыки).
В значимых файлах хранятся данные, в ярлыках хранятся ссылки на данные.
При копировании файла в папку, создается новый файл — копия.
При копировании значимого файла в папку, создается копия значения — всех данных.
При копировании ярлыка в файл, создается копия ярлыка.
Если открыть скопированный ярлык редактором ярлыков и изменить путь к файлу на другой, то изменится ли путь к файлу в оригинальном ярлыке, который был скопирован?
0
1 / 1 / 0
Регистрация: 17.04.2018
Сообщений: 236
23.04.2018, 09:37  [ТС] 10
Р. Лафоре стр. 187
0
Эксперт .NET
14870 / 11257 / 2950
Регистрация: 17.09.2011
Сообщений: 18,846
23.04.2018, 09:46 11
Цитата Сообщение от Ivanjs Посмотреть сообщение
Р. Лафоре стр. 187
Книги нет, но поиск по фамилии автора выдает только ссылки на книги по С++.
А тут вроде как идет обсуждение языка C#.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.04.2018, 09:46

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Передача строки в методе COM объекта
Имеется HRESULT q(BSTR *q1); STDMETHODIMP CSomeClass::q(BSTR q1) { *q1 = (BSTR)'Some...

Изменение переменной в методе
Здравствуйте, перешел из плюсов сюда. Хотелось бы узнать, как можно изменить переменную в методе?...

Изменение данных в методе
Как мне в зависимости от выбранного чекбокса передать другое значение (или число) в метод...

Изменение строки в методе
Добрый день. сделал функцию на получения полного пути из короткого но при выходе из функции...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.