|
28 / 28 / 5
Регистрация: 07.09.2012
Сообщений: 119
|
|
Как применить ref и out для ссылок на объекты07.09.2012, 14:21. Показов 23736. Ответов 56
Метки нет (Все метки)
Помогите пожалуйста разобраться новичку. Читаю шилдта, никак не могу въехать.... С применением Ref & out для переменных типа значений все предельно ясно. А вот при для объектов не могу понять...
Как вижу все это я: Типы значений: при передаче методу параметр получает копию значения аргумента. Соответственно, любые изменения в методе приводят к изменению копии аргумента, а значит, сам аргумент не изменяется. Все это исправляется при использования ref&out. Ссылочный тип: при передаче методу параметр получает копию ссылки на объект. Т.е. сама ссылка передается по значению. Получается, наш объект теперь имеет "псевдонимы", и его можно изменять из метода. Но что происходит при использовании ref с объектом??? Шилдт приводит пример с методом Swap, в котором изменяются ссылки на объекты.... (с 228) Кто бы мне объяснил весь процесс по пунктам... а то никак не могу понять, что вообще там происходит. Фраза: если модификаторы ref или out указывают на ссылку, то сама ссылка передается по ссылке - убила наповал))) Спасибо заранее
0
|
|
| 07.09.2012, 14:21 | |
|
Ответы с готовыми решениями:
56
Описать класс "Вектор" для хранения ссылок на объекты Как можно в textarea применить ::first-line, или как к первой строки применить стиль, внутри данного элемента |
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||
| 07.12.2016, 20:30 | ||
![]() null — это значение переменной, а не объекта, следовательно занулить можно только переменную. Объект либо существует, либо не существует. На него может быть ссылка, хранящаяся в переменной. Это может быть ссылка на существующий объект или ссылка "в никуда", то есть null. Сам объект по желанию вы удалять не можете — это область ответственности сборщика мусора.
1
|
||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
||||||||
| 07.12.2016, 22:06 | ||||||||
|
Но не соглашусь с вами(с терминологией),все таки в данном контексте не корректно говорить "переменная". К примеру :
.А теперь обратно к моему примеру(коду с коллекцией),получается так : если мы устанавливаем значение Null, то наша копия ссылки на объект(поле List),с которой происходит какие то действия внутри метода,теряет с ним(с полем) же связь(т.е. в памяти стека(!) больше не содержит в себе адрес самого объекта(объект List),а новое значение в виде Null и поэтому имеем такое же поведение,как и при создании нового объекта в контексте метода). А вопрос мой был связан с тем,что до конца не было понятно какое будет поведение,если придать значение Null внутри контекста метода .
0
|
||||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||||||||||
| 07.12.2016, 22:54 | ||||||||||
![]() с — это переменная типа MyClass, значением которой является ссылка на объект типа MyClass. Именно так правильно говорить с точки зрения терминологии. Из одной строчки кода невозможно сказать, где именно она будет расположена. Конкретно в Майкрософтовской реализации шарпа в стеке хранятся только несоптимизированные и незахваченные локальные переменные, которые не находятся в блоке-итераторе или асинхронном методе. Во всех остальных случаях переменная хранится в куче. Другие реализации шарпа имеют полное право хранить переменные где угодно — спецификация языка это разрешает. Лучше сразу стараться использовать правильную терминологию, чтобы в будущем не было путаницы — как, например, в ваших вопросах выше. Если MyClass — ссылочный тип, то значением переменной является либо ссылка на экземпляр типа MyClass или его наследников, либо null. Если MyClass — значимый тип, то значением переменной является сам экземпляр.
Если хорошо усвоить вышеприведенные пункты, то все непонятные моменты должны исчезнуть. На предыдущих страницах есть несколько приблизительных иллюстраций с расположением и порядком создания значений в памяти. Приблизительных — потому что там, в частности, явно разделены стек и куча, а разные реализации шарпа имеют право хранить переменные там, где им вздумается.
1
|
||||||||||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
|||||||||||||||
| 07.12.2016, 23:53 | |||||||||||||||
|
Тогда вопрос остается открытым. Что такое указатель и что такое ссылка в контексте управляемой памяти языка C#? Я в последнее время углубляюсь по теме "как CLR управляет\распределяется памятью". Даже если взять ваши сообщение из этой темы(которые датируются 2012ом годом),или к примеру Рихтера,или кучу других в статьей,то можно увидеть одну закономерность(и иллюстрации в виде картинок),а именно: ссылки ссылочного типа размещаются в стеке(!). Странно,хотя вполне ожидаемо(в случае как и с жит-компиляторами,которые могут быть оптимизированы по разному,соответственно на выходе разный IL код,а как итог совсем другое поведение). Относительно переменной,получается что каждый раз нам нужно тянуть тонну слов(см. комментарий к коду ):
![]() И стоит ли вообще на этом заострять свое внимание? ![]() Не по теме: может привести вам ряд статей(ссылки и отсылки к книгам,где авторы яро и смело бьют себе в грудь и уверяют,мол ссылки ссылочного типа хранятся в стеке),хочу услышать ваше мнение. А Т.е. перефразирую для вас
.Это и так понятно,за исключением момента с трактовкой объекта,то бишь что то уж вы сильно обостряете внимание на этом.
0
|
|||||||||||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||||||
| 08.12.2016, 00:57 | |||||||||||||
|
Ссылка — это больше похоже на дескриптор, с помощью которого можно получить доступ к объекту. По факту в майкрософтовской реализации шарпа экземпляры ссылочных типов всегда хранятся в куче. Вполне можно сделать оптимизацию, которая в некоторых случаях будет их держать и в куче, но эта оптимизация не реализована. Другие компиляторы могут реализовать такую оптимизацию, запрета нет. Люди, знакомые с языком, в общении друг с другом прекрасно понимают о чем идет речь, а количество звуков экономится. Проблемы начинают возникать тогда, когда эти люди начинают жаргон использовать в общении с теми, кто язык только еще изучает. Или, того хуже, начинают писать статьи/руководства/книги с использованием "словечек". Можно серьезно запутаться. ![]() ![]() Если постоянно использовать правильную терминологию, то разумеется можно язык сломать. Именно поэтому в любой профессии и существует такая штука, как профессиональный жаргон. Возьмите да протестируйте всё сами — это закаляет характер ![]() Зацикливаться — я думаю не стоит, если вы не хотите написать свой собственный компилятор. Огромное количество людей потратило много времени, реализуя сборщик мусора, — именно для того, чтобы вы себе не забивали голову местоположнием и временем жизни объектов. Но только перед тем, как приводить статьи, прочитайте те абзацы по-внимательнее: возможно, речь там все-таки идет об экземплярах ссылочных типов, а не о ссылках на них. Ссылка — это всегда либо валидный дескриптор объекта, либо null. Их важно различать, особенно в шарпе, т.к. там есть и сылки, и указатели. То есть ссылка — это абстракция, некая сущность, с помощью которой получается доступ к объекту. Скажу по секрету: в шарпе ссылки реализованы через обычные указатели, но с определенными жесткими ограничениями. Например, ссылка не может ссылаться на часть объекта. Но то, что ссылки в шарпе реализованы через указатели — это опять же деталь реализации. Какой-нибудь Mono/Xamarin имеет полное право реализовать ссылки через самые настоящие дескрипторы. Есть такое выражение, что если что-то выглядит как утка и крякает как утка, то это утка. Вот это выражение можно перефразировать и для ссылок в шарпе: ссылкой называется сущность, которая имеет поведение и все свойства ссылки согласно спецификации языка. Я весь списк сходу не припомню, но два важных пункта — это всегда известен статический тип (даже для null) и если ссыла не null, то статический тип ссылки всегда совместим с фактическим типом объета, на который она ссылается. Говоря проще, если ссылка имеет определенный тип, то и ссылаться она может только на этот же тип или его наследников. Это ограничение отсутствует для указателей.
1
|
|||||||||||||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
|||||||||||
| 08.12.2016, 01:46 | |||||||||||
![]() нет,именно "ссылки" или как вы их называете "переменные",расположены в стеке,а сам объект и тип объекта в куче(про что я писал выше).
[image]https://www.cyberforum.ru/attachments/771016d1481149908[/image] Статья 1 Статья 2 Статья 3 Статья 4 Ну и у Рихтера в 4 главе есть нечто подобное .
0
|
|||||||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||||||||||||||||
| 08.12.2016, 02:33 | ||||||||||||||||
|
Почему вам интересно, каким образом реализованы ссылки? ![]() Ссылка — это значение, переменная — это хранилище. Значение переменной ссылочного типа — ссылка. Проводя аналогию, переменная — шкатулка, а ссылка — это листочек с указанем где найти то, что вам нужно, хранящийся в этой шкатулке. Особенно если учесть, что поле класса — это тоже переменная.
Ну и, конечно же, никто почему-то ничего не сказал про регистры, будто их вообще не существует.
В шарпе есть два типа памяти: долговременная и кратковременная. Долговременная — это куча, управляемая и неуправляемая. Кратковременная — это стек вызовов и регистры процессора. Выбор памяти под переменную зависит не от того, значимого она типа или ссылочного (тогда бы они назывались не значимые и ссылочные, а стековые и кучевые), а от того, как долго переменная будет использоваться. Если время жизни переменной кратко и предсказуемо, то память под нее будет выделена в стеке или значение переменной будет храниться в регистре процессора. Если время жизни переменной непредсказуемо, то память под нее будет выделена в куче. Обращаю внимание: речь идет о переменных, а не об экземплярах типа. Экземпляры ссылочных типов всегда создаются в куче (в М-й реализации языка). Экземпляры значимых типов — там, где создается сама переменная, т.к. экземпляр хранится в переменной. Потому ответом на этот вопрос может быть только встречный вопрос: о каком компиляторе какой версии идет речь?
1
|
||||||||||||||||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
||||||||||||
| 08.12.2016, 03:08 | ||||||||||||
|
Отсюда и конфуз у меня . ?В общем посыл понял. И как вы описали ранее(сообщение датируемым 2012ым годом), и моя иллюстрация(она очень похоже на ту,что у Рихтера),имеет место быть,но только как случай(то бишь не всегда).
0
|
||||||||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||
| 08.12.2016, 03:14 | |||||||||
|
Переменная — это просто хранилище информации, в котором может лежать какое-нибудь значение. Одно из возможных значений — ссылка на экземпляр объекта. Как видите, уже один этот факт опровергает всех любителей рассказать о том, что значимые типы всегда живут в стеке. ![]() Ведь ref/out — это про переменные, а не про экземпляры. У вас же вопросы возникли по поводу ref/out, так? Если все-таки интересно, то в майкрософтовской версии шарпа объекты ссылочных типов реализованы как блоки памяти, первые байты которых, т.н. заголовки, хранят определенные метаданные об экземпляре (ссылку на тип, блок синхронизации и т.д.). Ссылка на такой объект реализована как указатель на этот заголовок.
0
|
|||||||||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
|||||||
| 08.12.2016, 17:50 | |||||||
Разве я утверждал,что ValueType хранятся всегда и только всегда в стеке? ![]() Я вам даже больше скажу,в каких именно случаях ValueType хранится в Хипе: 1. Если ValueType упакован(boxed) - хранится в хипе 2. Если ValueType являются полем класса - хранится в хипе 3. В случае замыкания с анонимными методами(а мы ведь знаем,что при Closure,компилятор ретранслирует код в доп. класс,где переменная становится полем,отсюда по логике пункт №2) - хранится в хипе 4. Если находится в блоке итератора(yield,который разворачивает класс с интерфейсом IEnumerable) - хранится в хипе Речь шла исключительно только об ReferenceType , т.к. не было понятно мне,какое поведение получает ReferenceType в контексте метода,если придать значение Null. Заметьте,я ведь ни слова не говорил об ValueType в моих сообщениях.
0
|
|||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||||||
| 08.12.2016, 20:40 | ||||||
![]() Вы вроде бы такого не говорили. Добавьте еще асинхронные методы пятым пунктом.
1
|
||||||
|
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
|
||||
| 08.12.2016, 22:37 | ||||
, видимо мы друг друга не поняли,и обсуждали "более" глобально. Но опять же,вопрос стоял о ReferenceType.В общем благодарю за быстрые ответы.
1
|
||||
|
3 / 3 / 1
Регистрация: 12.04.2015
Сообщений: 74
|
||
| 17.12.2016, 02:41 | ||
|
Добрый день, я сторонний наблюдатель, тему прочитал целиком.
И, соответственно, я считал, что при передаче (из main, например) в метод ссылочного типа создаётся копия указателя на экземпляр класса. Соответственно, мы можем изменять этот указатель, чтобы он указывал на что-нибудь другое, а исходный указатель и то, на что он указывает остаются без изменений, верно? Вопрос небольшой, с Вашего позволения, kolorotur, ответьте, пожалуйста: Если при передаче ValueType (ref int index) с модификатором ref у нас должна передаваться ссылка на область памяти, содержащая нашу переменную index, то при каждой передаче этой ссылки (ref int index) в метод, будет ли у нас будет создаваться дополнительный указатель, содержащий значение этой области памяти или же в метод будет передаваться лишь сама ссылка? Другими словами, является ли на низком уровне передача значимого типа по ссылке передачей по ссылке или по сути является передачей с созданием нового указателя? (Меня это интересует в контексте затрат памяти на указатели при передаче значимого типа по ссылке множество раз во вложенные вызовы различных методов)
0
|
||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||
| 17.12.2016, 04:29 | |||
|
В худшем случае будет создаваться указатель на переменную при каждом вызове. Единственная "проблема", которую может создать дополнительный указатель — это взорванный стек при длинной цепочке вызовов, но если у вас столько вызовов, что стек взрывается из-за локальной переменной в 32/64 бита, то проблема кроется уже не в наличии указателя, а в наличии такой глубины вызовов.
0
|
|||
|
3 / 3 / 1
Регистрация: 12.04.2015
Сообщений: 74
|
||
| 17.12.2016, 06:03 | ||
|
Заранее, извиняюсь за оффтоп (Если мой вопрос можно счесть оффтопом)
Просто интересно, будет ли выделяться каждый раз память под этот указатель (или ссылку) "ref"? (Если в случае с C++ мы точно знаем, что для параметра (&index) лишних операций по выделению памяти не происходит)
0
|
||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||||||
| 17.12.2016, 17:23 | |||||||||||||
|
Конкретно в майкрософтовской реализации компилятора под настольную версию Windows просто создается параметр-адрес, как в плюсах. Было:
Лучше так не делайте, поскольку ключевое слово ref ничего не говорит об используемой памяти, у него ровно одно семантическое значение: передача переменной по ссылке. Лучше все-таки не строить логику приложения, опираясь на детали реализации компилятора или среды выполнения — в истории огромная масса примеров, когда написанное подобным образом приложение просто переставало работать при выходе очередного обновления или при переходе на новую версию ОС. А виновата, как всегда, "тупая винда"
0
|
|||||||||||||
|
3 / 3 / 1
Регистрация: 12.04.2015
Сообщений: 74
|
||
| 18.12.2016, 00:02 | ||
0
|
||
| 18.12.2016, 00:02 | |
|
Перебор ссылок на объекты
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
|
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
|
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701
Купил два термопринтера QR701.
На сэлф-тесте написано:
Language: PC936 (GB18030).
Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
|
Создание формы заимствованного документа
Maks 03.08.2026
Задача:
Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также
табличная часть со следующими реквизитами:
- Расчетный счет покупателя. . .
|
|
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача:
В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
|
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов.
Логика кажется понятной:
1. Находим ключевые слова.
2. Добавляем их на. . .
|
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302
Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
|
SUNO Ai - Река Без Дна
zorxor 31.07.2026
Автор стихотворения - астрофизик Марина Катыс
Ссылка на сгенерированную музыкальную композицию:
https:/ / suno. com/ song/ 6f6e5464-b290-4650-be6c-44c85f8d8013
Я говорю, что Время- как вода
течет. . .
|