Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/125: Рейтинг темы: голосов - 125, средняя оценка - 4.60
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119

Как применить ref и out для ссылок на объекты

07.09.2012, 14:21. Показов 23690. Ответов 56
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помогите пожалуйста разобраться новичку. Читаю шилдта, никак не могу въехать.... С применением Ref & out для переменных типа значений все предельно ясно. А вот при для объектов не могу понять...
Как вижу все это я:
Типы значений: при передаче методу параметр получает копию значения аргумента. Соответственно, любые изменения в методе приводят к изменению копии аргумента, а значит, сам аргумент не изменяется. Все это исправляется при использования ref&out.
Ссылочный тип: при передаче методу параметр получает копию ссылки на объект. Т.е. сама ссылка передается по значению. Получается, наш объект теперь имеет "псевдонимы", и его можно изменять из метода.
Но что происходит при использовании ref с объектом???
Шилдт приводит пример с методом Swap, в котором изменяются ссылки на объекты.... (с 228)
Кто бы мне объяснил весь процесс по пунктам... а то никак не могу понять, что вообще там происходит.
Фраза: если модификаторы ref или out указывают на ссылку, то сама ссылка передается по ссылке - убила наповал)))
Спасибо заранее
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.09.2012, 14:21
Ответы с готовыми решениями:

Использование модификатора ref для ссылок на объекты (для чайника)
Всем привет! Изучаю c# по учебнику Шилдта, также разбираю примеры из него. Из примера ниже мне непонятно. Зачем здесь использовать...

Описать класс "Вектор" для хранения ссылок на объекты
Объявить класс "Вектор" для хранения ссылок на объекты. Класс должен иметь следующие поля: -массив ссылок, который может расти ...

Как можно в textarea применить ::first-line, или как к первой строки применить стиль, внутри данного элемента
Да и вообще, для этого можно ли еще что-либо вложить в данный элемент, кроме как текста? Добавлено через 2 часа 3 минуты вопрос...

56
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
07.09.2012, 17:10  [ТС]
Студворк — интернет-сервис помощи студентам
В продолжение моего вопроса:
1. Существует некая ячейка памяти с адресом 0хFF, в которой хранится объект с именем Петя.
2. Существует ссылка на него, расположенная по адресу 0хАА.
При вызове метода NoRef создается ячейка памяти, хранящая значение 0хFF (т.е. копия ссылки) - это как я понимаю и есть параметр метода.
При вызове метода Ref создается ячейка памяти, получающая значение 0хАА (получается ссылка на ссылку и также являющаяся параметром метода)

3. Далее существует некая ячейка памяти с адресом 0xDD, в которой создается объект с именем Вася.
При вызове метода NoRef параметру (с текущим значением 0xFF, указывающему на объект с именем Петя) присваивается значение 0хDD. Теперь параметр хранит ссылку на объект с именем Вася. естественно, ячейка памяти по адресу ОхАА не изменяется и все также содержит значение 0хFF.

При вызове же метода Ref, ячейка памяти, прежде хранящая значение 0хAA, получает новое значение 0хDD. Отныне она хранит ссылку на объект с именем Вася.

Так в чем же разница????? Ведь при вызове метода Ref ячейка памяти расположенная по адресу 0хАА и хранящая 0хFF не изменяется ни в том, ни в том случае...

Где ошибка в моей логике???
0
51 / 38 / 5
Регистрация: 14.01.2012
Сообщений: 127
07.09.2012, 21:54
temcha,
1. Существует некая ячейка памяти с адресом 0хFF, в которой хранится массив интов
2. НЕ существует ссылка на него, в том смысле, что переменная типа int[] возвращает именно объект, массив:
C#
1
2
3
4
int[] A1 = new int[10];
int[] B1 = A1;
A1 = new int[9];
Console.WriteLine(A1.Length + " " + B1.Length);
При вызове метода NoRef создается ячейка памяти, хранящая значение ячейки по адресу 0хFF (т.е. копия объекта) - это как я понимаю и есть параметр метода - можно сказать и так, главное что метод NoRef работает с ячейкой памяти содержимое которой такое же как у ячейки по адресу 0хFF, но это другая ячейка.
При вызове метода Ref метод в итоге работает с ячейкой по адресу 0хFF.
Вообще, имхо, думать, что у нессылочных типов есть ссылка на них - бессмысленно. Лучше считать что переменная - это есть ячейка в памяти, а не ссылка на ячейку для нессылочных типов или ссылка на ссылку для ссылочных. При использовании ref и out переменная, переданная в метод извне - это та же переменная принятая как параметр в методе, хотя они могут по-разному называться. То что ref создает ссылку на объект - как бы верно, но в методе мы получаем ту же, уже готовую ячейку памяти, только работаем с этой ячейкой памяти уже через другую переменную. Т.е. в случае с ref лучше забить на то что это ссылка, так как эту ссылку никак нельзя использовать, ref применяется, можно сказать, для использования этой же переменной в методе. На мсдн для новых версий студии в определении ref присутствует слово ссылка, но в версии Visual Studio .NET 2003
не присутствует, мне оно кажется более верным:
The ref method parameter keyword on a method parameter causes a method to refer to the same variable that was passed into the method. Any changes made to the parameter in the method will be reflected in that variable when control passes back to the calling method.
А в более новых есть замечание:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.
Первые два предложения, перевод:Не путайте понятия передача по ссылке с понятием ссылочных типов. Эти два понятия не совпадают.
0
 Аватар для Евгений В
912 / 672 / 134
Регистрация: 01.03.2010
Сообщений: 1,279
07.09.2012, 22:22
Цитата Сообщение от temcha Посмотреть сообщение
Так в чем же разница????? Ведь при вызове метода Ref ячейка памяти расположенная по адресу 0хАА и хранящая 0хFF не изменяется ни в том, ни в том случае...
Как же не меняется. Вначале она ссылалась на 0хFF (объект Петя), а после ref на 0xDD (объект Вася)
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.09.2012, 11:48
Лучший ответ Сообщение было отмечено как решение

Решение

temcha, как говорится, одна картинка стоит тысячи слов, потому вот вам несколько рисунков плюс многабукаф.

Вот код, который будет рассматриваться практически пошагово с точки зрения памяти:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Person
{
    public string Name;
    public int Age;
}
 
static void Main()
{
    Person person;
    person = new Person();
    person.Name = "Вася";
    person.Age = 12;
 
        NoRef(person);
        Ref(ref person);
}
 
static void NoRef(Person p)
{
    p = new Person();
    p.Name = "Петя";
    p.Age = 6;
}
 
static void Ref(ref Person pref)
{
    pref = new Person();
    pref.Name = "Коля";
    pref.Age = 42;
}
Перво-наперво нужно обратить внимание на то, что при компиляции в байткод имена переменных будут заменены адресами памяти. Имена - они исключительно для вашего удобства при написании кода, не более чем псевдонимы. А для одного и того же участка памяти может существовать несколько псевдонимов.

Далее идет описание каждого участка кода и того, что происходит в памяти.
Для удобства на изображениях в каждой ячейке памяти содержится четыре байта - в соответствии с размером регистра на x86.

Дисклэймер: на изображениях приведено приблизительное расположение элементов в памяти, с точностью исключительно до того, что нас интересует. Потому любители пояснить о том, что ссылка - это не то же самое, что указатель, что она не указывает на адрес первого поля класса, что при инициализации объекта создается временная переменная, что помимо полей экземпляра в памяти хранится еще дополнительная информация для рантайма и т.д., могут расслабиться - пост не об этом.

На начало запуска метода Main память имеет примерно такой вид:


Далее выполняются вот эти строчки:
C#
1
2
3
4
    Person person;
    person = new Person();
    person.Name = "Вася";
    person.Age = 12;
Что происходит:
1. На стэке по адресу 0xFF выделяется место под переменную person, которое на данный момент содержит значение 0x00, то есть null.
2. В куче по адресам с 0x4C по 0x48 выделяется память под новый экземпляр класса Person, размер экземпляра равняется восьми байтам - 4 байта для ссылки на строку (Name) и 4 байта на целое число (Age). (тем, кто хочет сказать, что размер объекта по факту больше восьми байт - читать дисклэймер выше).
3. Адрес нового экземпляра в куче присваивается ссылке person, хранящейся в стеке по адресу 0xFF. То есть переменная person при компиляции будет заменена на 0xFF и значение этой ячейки, равное 0x4C, будет являться адресом экземпляра в куче.
4. Полю name присваивается адрес на новый экземпляр строки - в куче выделяется под нее память, записываются данные и адрес новой строки присваивается ссылке. Строки в .NET хранятся в UTF-16, потому на каждый символ выходит по два байта, то есть в каждой ячейке будет храниться по два символа.
5. По адресу 0x48 прописывается возраст Васи.

После всех этих манипуляций память имеет примерно такой вид:

Подытожим:
а). person - это псевдоним для адреса 0xFF, по которому прописан адрес объекта в куче.
б). person.Name - это псевдоним для адреса 0x4C, по которому прописана ссылка на строку - имя человека.
в). person.Age - это псевдоним для адреса 0x48, где хранится возраст Васи.

Далее происходит вызов метода NoRef
C#
1
NoRef(person);
Что происходит:
1. На стеке для аргумента "p" выделяется память по адресу 0xFB, куда записывается значение переменной "person", то есть значение ячейки памяти по адресу 0xFF.
2. Контекст выполнения переходит в метод NoRef.


Итог: в куче лежит один объект, расположенный по адресу 0x4C. В стеке имеются две ячейки памяти по адресам 0xFF (псевдоним person) и 0xFB (псевдоним p), в которых хранится адрес этого объекта.

Далее выполняется код метода NoRef:
C#
1
2
3
4
5
6
static void NoRef(Person p)
{
    p = new Person();
    p.Name = "Петя";
    p.Age = 6;
}
1. В куче создается новый экземпляр класса Person
2. Ссылка на этот объект записывается в стек по адресу 0xFB, имеющий псевдоним p.
3. В куче создается новый экземпляр строки по адресу 0x30 и этот адрес записывается в ячейку 0x3C, имеющую псевдоним p.Name.
4. Возраст Пети записывается в память по адресу 0x38, имеющий псевдоним p.Age.

Вид на память аккурат перед завершением метода NoRef:


Далее метод NoRef завершается, указатель стека возвращается на прежнюю позицию, тем самым выводя переменную p из области видимости. Так как p была единственной ссылкой на Петю, его судьба нам больше неизвестна - он стал кандидатом на уничтожение сборщиком мусора и в данный момент является котом Шрёдингера.

Примерный вид на память сразу же после завершения метода NoRef:

Свежесозданный Петя в памяти еще есть, а может быть уже и нет.

Далее происходит переключение контекста на выполнение метода Ref.
C#
1
Ref(ref person);
Так как переменная person передается по ссылке, то в стеке не выделяется память под новую переменную, а всего-навсего ячейке по адресу 0xFF присваивается новый псевдоним - pref:


После чего выполнение переходит в метод Ref и в байткоде везде, где используется переменная pref будет подставлен адрес 0xFF - всё просто.
C#
1
2
3
4
5
6
static void Ref(ref Person pref)
{
    pref = new Person();
    pref.Name = "Коля";
    pref.Age = 42;
}
А происходит в коде следующее:
1. В куче выделяется память под новый экземпляр класса Person.
2. Адрес нового объекта 0x2C записывается в память под псевдонимом pref, то есть в ячейку 0xFF
3. Так как на Васю больше никто не ссылается, он становится кандидатом на уничтожение сборщиком.
4. Как в предыдущие разы, создается новый экземпляр строки по адресу 0x20, туда записывается значение "Коля" и адрес новой строки записывается в ячейку 0x2C, носящую псевдонимы pref.Name и person.Name
5. По адресу 0x28 (псевдонимы pref.Age и person.Age) записывается возраст Коли.

Вид на память перед завершением работы метода Ref:


Метод завершается, псевдоним pref уничтожается, в итоге у ячейки 0xFF остается один-единственный псевдоним person. Обратите внимание, что в байткоде никаких псевдонимов не будет - будут тупо адреса памяти.
Вид на память сразу после завершения работы метода Ref и перед завершением метода Main:


Примерно так все и происходит.
Пример, конечно, больше подходит под С++, т.к. в шарпе структура объектов сложнее, чем просто подряд идущие поля, а сама ссылка - не тупо указатель с адресом, а больше похожа на дескриптор объекта, но для описания общей картины, думаю, пойдет.
8
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
08.09.2012, 13:16  [ТС]
ОГРОМНОЕ спасибо за прояснение ситуации.
Получается ссылка на ссылку в методе ref всего навсего добавление нового псевдонима на время действия метода? я раньше думал что это выделение ячейки памяти в стеке, которая будет хранить значение адреса исходной ссылки...
и еще 2 вопросика: в С# массив является объектом, значит будет происходить все то же? и что происходит в памяти при присваивании объекта объекту? К примеру, мы в методе Ref сделали что то такое:
C#
1
2
Person t;
t = pref;
или вообще в метод ref передали 2 объекта ob1 и ob2 и написали:
Person t;
C#
1
2
3
t = ob1;
ob1 = ob2;
ob2 = t;
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.09.2012, 13:25
Цитата Сообщение от temcha Посмотреть сообщение
олучается ссылка на ссылку в методе ref всего навсего добавление нового псевдонима на время действия метода?
Да, но я опять же замечу: псевдонимы - это для вас, для разработчика. В байткоде все эти имена переменных будут заменены фактическими адресами в памяти. То есть и в Main и в Ref будет использоваться адрес 0xFF.

Цитата Сообщение от temcha Посмотреть сообщение
я раньше думал что это выделение ячейки памяти в стеке, которая будет хранить значение адреса исходной ссылки...
Если делать через указатели, то да - создается новая ячейка, в которой хранится значение адреса переменной под вопросом. Например:
C#
1
2
long x = 42; // Выделяется ячейка в 8 байт, в которых будет прописано число 42.
int* ptr = &x; // Выделяется ячейка в 4 байта (8 на х64), в которой будет храниться адрес первой ячейки
В случае же с ref просто передается адрес уже существующей ячейки, без выделения дополнительной памяти под указатель.

Цитата Сообщение от temcha Посмотреть сообщение
в С# массив является объектом, значит будет происходить все то же?
Да.
1
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
08.09.2012, 13:51  [ТС]
Ув. kolorotur, по поводу второй части моего вопроса относительно присваивания, приведу кусочек кода на котором я пытаюсь разобраться что происходит при присваивании:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class MyClass
    {
        public string name;
 
 
        public void Swp(ref MyClass ob1, ref MyClass ob2)
        {
            MyClass t;
 
            t = ob1;
            ob1 = ob2;
            ob2.name = "Толик";
            
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyClass x = new MyClass();
            MyClass y = new MyClass();
            x.name = "Вася";
            y.name = "Петя";
            Console.WriteLine(x.name);
            Console.WriteLine(y.name);
            x.Swp(ref x, ref y);
            Console.WriteLine(x.name);
            Console.WriteLine(y.name);
            Console.ReadKey();
 
        }
    }
почему в итоге получается Вася, Петя а потом 2 Толика?
Не могли бы Вы пояснить что происходит с точки зрения памяти во время присваивания? Спасибо...
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.09.2012, 14:18
C#
1
2
3
4
5
            MyClass t;
 
            t = ob1;
            ob1 = ob2;
            ob2.name = "Толик";
Вы забыли о переменной t, в результате и ob1 и ob2 ссылаются на Петю, а Вася уходит из области видимости, т.к. на него ссылок не осатется.
C#
1
2
3
4
5
var t = ob1;
ob1 = ob2;
ob2 = t;
 
ob2.Name = "Толик";
0
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
08.09.2012, 16:39  [ТС]
да, с этим разобрался, спасибо. А где бы почитать о принципах сохранения информации в памяти?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.09.2012, 16:47
Даже не знаю что посоветовать...
Я еще в ВУЗе проходил архитектуру ЭВМ (на примере MIPS, правда) - вдалбливали хорошо, до сих пор помню зачеты по ассемблеру.

Добавлено через 26 секунд
Дома может где-то книжка по предмету еще лежит - могу глянуть название. Правда, она на английском.
0
3 / 3 / 0
Регистрация: 03.06.2012
Сообщений: 38
08.09.2012, 18:01
kolorotur,
Я правильно Вас понял?

Допустим есть два объекта c псевдонимами ob1 и ob2

Далее, для примера:
ob1 (адрес 0ХFF) ссылается на объект по адресу 0Х4С
ob2 (адрес 0ХFB) ссылается на объект по адресу 0Х3С

Теперь проведем такое действие
ob1=ob2

Получаем, что адрес 0ХFB имеет теперь два псевдонима ob1 и ob2
а адрес 0ХFF и объект, на который он указывает по адресу 0Х4С попадают под раздачу мусорщика.

Все верно?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.09.2012, 19:00
Alexsis6911, да, все верно, только адрес 0xFF не попадает под раздачу мусорщика, т.к. хранится в стеке, а там мусорщик не прибирается. Просто до завершения контекста остается неиспользуемая "грязная" ячейка в стеке по адресу 0xFF.
1
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
08.09.2012, 19:26  [ТС]
буду благодарен, если скажешь название, пусть и на английском
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.09.2012, 21:36
David A. Patterson, John L. Hennessy. "Computer Organization and Design. The Hardware/Software Interface".

У меня старенькое издание, но она в декабре 2011 года обновилась до четвертого издания - ищите его.
Вот ссылка на магазин издателя: http://store.elsevier.com/prod... ame=search
В русском переводе, наверное, тоже где-то есть.

Книжка очень мощная - рекомендую. Там от работы компиляторов до машинных инструкций и до построения логических схем ЦПУ (на их основе уже электрические схемы чертят, а дальше - только железо).
Работа с памятью тоже рассматривается, причем работе с иерархиями памяти (кэш, виртуальная память и т.д.) отдельная глава отведена. Рассматриваются реальные модели памяти Интела и АМД.
Ну и к задней корочке прицеплен сидюк с примерами, ассемблером, софтинками типа всяческих эмуляторов МИПСа и прочими вкусностями.

Приятного чтения

Не по теме:

P.S. Надо будет у издательства деньжат за рекламу затребовать...

1
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
08.09.2012, 22:45
kolorotur,

Не по теме:

всегда, когда вижу новую книгу в сети (ну или совет), думаю "Неплохо бы скачать", а после фразы "сидюк с вкусностями" тут же приходит на ум "а может и купить"... :)



Добавлено через 8 минут
Вот нашел в магазине (модеры, звиняйте, но найти просто по поисковику было трудно):
http://www.labirint.ru/books/317754/
Если все же затрете, описание
Паттерсон, Хеннесси: Архитектура компьютера и проектирование компьютерных систем. Классика Computers Science
Автор: Паттерсон Дэвид, Хеннесси Джон
Переводчик: Вильчинский Н.
Редактор: Кривцов А.
Издательство: Питер, 2012 г.
Серия: Классика computer science
Страниц: 784 (Офсет)
0
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
06.12.2016, 00:08
kolorotur,
Почему у коллекций такого поведения нет?(они изменяются,даже если нет параметров ref / out)
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
06.12.2016, 01:04
Цитата Сообщение от Vasyan Посмотреть сообщение
Почему у коллекций такого поведения нет?
Вы путаете объект и переменную.
ref/out позволяет изменять переменную.
А добавляя/удаляя элементы из коллекции, вы меняете объект.
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
06.12.2016, 18:01
Цитата Сообщение от kolorotur Посмотреть сообщение
Вы путаете объект и переменную.
ref/out позволяет изменять переменную.
А добавляя/удаляя элементы из коллекции, вы меняете объект
Да,пожалуй вы правы.
Вот в этом онлайн компиляторе пробовал данный код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Collections.Generic;
                    
public class Program
{
    static List<string> List = new List<string>();
    
    public static void Main()
    {
        for(int i = 0; i < 10; i++)
            List.Add(String.Format("My item# {0}",i));
                     
        Console.WriteLine("Лист до вызова метода\n");
        
        foreach(var item in List)
            Console.Write("\t" + item);
        
        ModifyList(List);
        
        Console.WriteLine("\n\nЛист после вызова метода\n");
        
        foreach(var item in List)
            Console.Write("\t" + item);
    }
                     
    static void ModifyList(List<string> Lst)
    {
        Lst = new List<string>();
        
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
    }
}
И видимо по глупости,в этом методе
C#
1
2
3
4
5
6
7
8
static void ModifyList(List<string> Lst)
    {
        Lst = new List<string>();
        
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
    }
Использовал не входной параметр Lst,а поле List,благодаря чему,получалось менять поведение,даже после
C#
1
List = new List<string>();
без ключевых слов ref \ out.
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
07.12.2016, 19:54
Цитата Сообщение от kolorotur Посмотреть сообщение
А добавляя/удаляя элементы из коллекции, вы меняете объект
Вот у меня возник такого рода вопрос.
Почему мы не можем придать null объекту,ссылку которого,передали как параметр в методе?

Опять же,если рассмотреть мой код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
                    
public class Program
{
    static List<string> List = new List<string>();
    
    public static void Main()
    {
        for(int i = 0; i < 10; i++)
            List.Add(String.Format("My item# {0}",i));
                     
        Console.WriteLine("Лист до вызова метода\n");
        
        foreach(var item in List)
            Console.Write("\t" + item);
        
        ModifyList(List);
        
        Console.WriteLine("\n\nЛист после вызова метода\n");
        
        foreach(var item in List)
            Console.Write("\t" + item); //выведет на экран 10 элементов со значением My item и еще добавиться три эл-та с значением "bla bla bla"
    }
                     
    static void ModifyList(List<string> Lst)
    {        
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
    }
}
То почему мы не можем за-Null"ить объект,имея копию ссылки на сам объект?
Т.е. если в метод добавить этот код:
C#
1
2
3
4
5
    static void ModifyList(List<string> Lst)
    {        
        Lst = null; // то это никак не повлияет на сам объект,то бишь поле List останется таким же,как и до вызовы метода ModifyList
    
    }
В случае,когда мы инициализируем новый объект:
C#
1
2
3
4
5
6
7
tatic void ModifyList(List<string> Lst)
    {       
        Lst = new List<string>(); // тут все понятно,по сути в какой то степени мы разыменовывали копию ссылки на объект List и создали новый объект,который будет жить в контексте метода ModifyList
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
        Lst.Add("bla bla bla");
    }
Но я что то не припомню,чтобы при присвоении Null, объект как то менялся в памяти(по типу создания нового объекта).
Другими словами, присвоение к Null или созданию нового объекта в контексте метода(в нашем случае это ModifyList),идет разыменовывание копии ссылки и соответственно работа уже проводиться со всем другим объектом?
0
.NET senior
 Аватар для bax_tang
441 / 359 / 137
Регистрация: 23.09.2016
Сообщений: 980
07.12.2016, 20:06
Vasyan, насколько я помню, чтобы изменить значение поля, нужно напрямую записать значение, обращаясь к полю класса напрямую. Параметры в метод передаются по значению, то есть для ссылочных типов создается копия исходной ссылки (физически - выделяется новая область памяти, содержащая адрес объекта в куче). Если теперь изменить эту ссылку (создать новый объект и сохранить его адрес), то на оригинальную это никак не повлияет (и в то же самое время мы можем как угодно менять состояние объекта по этой ссылке).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.12.2016, 20:06

Перебор ссылок на объекты
Здравствуйте, у меня имеется объект (корабль линкор). Перебираю с помощью for. Так как объект может быть уничтожен другим объектом, на его...

Vector ссылок на объекты класса
У меня есть свой класс объекта. И при создании новых экземпляров данного объекта, мне нужно чтобы в vector заносилась ссылка на него...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
сукцессия 43. Вторая научная статья за месяц- прайминг и гатгил
anaschu 25.07.2026
две стороны одной монеты
Более приземисто - Эстафету хвоста в .cdl (деревья эстафеты в сад).
Hrethgir 24.07.2026
В будущем, после написания блока инверсии обхода дерева (эстафеты хвоста), я планирую вернуться к нашему прошлому разговору о том, обладают ли знания целеполаганием. Тогда я пришел к выводу, что. . .
Вот представьте что вам дали бессмертие.
kumehtar 24.07.2026
Вот представьте что вам дали бессмертие, ничего более не меняя. Вообще ничего, только бессмертие в нынешнем виде. Рады были бы? Что бы вы тут делали всё это время? Никакой пенсии. Никакого нового. . .
сукцессия 41
anaschu 24.07.2026
Численная верификация бифуркации в агентной модели лесной сукцессии: от одного параметра к ансамблю Автор: пользователь @Shumilov_AS | Раздел: Прикладная математика / Численные методы Кратко. . .
сукцессия 40. Ансамблевая кластерная параметризаци, часть 1.
anaschu 24.07.2026
Пр# Сопровождение научной статьи ИИ-ассистентом: подготовка публикации и калибровка агентно-ориентированной модели сукцессии микоризных систем **Полевые заметки о двухнедельной совместной работе**. . .
Теория всего 12. ВГК на планете в стратегической игре "терра"
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru