Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.60/125: Рейтинг темы: голосов - 125, средняя оценка - 4.60
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
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.09.2012, 14:21
Ответы с готовыми решениями:

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

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

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

56
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
07.12.2016, 20:30
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Vasyan Посмотреть сообщение
То почему мы не можем за-Null"ить объект,имея копию ссылки на сам объект?
Вы опять путаете переменую и объект

null — это значение переменной, а не объекта, следовательно занулить можно только переменную.
Объект либо существует, либо не существует. На него может быть ссылка, хранящаяся в переменной. Это может быть ссылка на существующий объект или ссылка "в никуда", то есть null.
Сам объект по желанию вы удалять не можете — это область ответственности сборщика мусора.
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
07.12.2016, 22:06
Цитата Сообщение от kolorotur Посмотреть сообщение
null — это значение переменной, а не объекта, следовательно занулить можно только переменную
все,теперь понятнее.
Но не соглашусь с вами(с терминологией),все таки в данном контексте не корректно говорить "переменная".
К примеру :
C#
1
2
3
MyClass c = new MyClass(); // с - это объект типа MyClass.
// Но на уровне памяти,получается что "с"(это указатель),который расположен
// в стеке,и который ссылается на адрес объекта типа MyClass в heap'e
И соответственно в совокупности этого механизма,мы говорим что с это объект типа MyClass,но не переменная типа MyClass .

А теперь обратно к моему примеру(коду с коллекцией),получается так :
если мы устанавливаем значение Null, то наша копия ссылки на объект(поле List),с которой происходит какие то действия внутри метода,теряет с ним(с полем) же связь(т.е. в памяти стека(!) больше не содержит в себе адрес самого объекта(объект List),а новое значение в виде Null и поэтому имеем такое же поведение,как и при создании нового объекта в контексте метода).

Цитата Сообщение от bax_tang Посмотреть сообщение
физически - выделяется новая область памяти, содержащая адрес объекта в куче
Так оно и есть,только правильнее сказать,что выделяется новая область памяти в стеке(для указателя копии,который работает с адресом оригинального объекта,расположенного в куче).
А вопрос мой был связан с тем,что до конца не было понятно какое будет поведение,если придать значение Null внутри контекста метода .
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
07.12.2016, 22:54
Цитата Сообщение от Vasyan Посмотреть сообщение
все таки в данном контексте не корректно говорить "переменная".
Неправда ваша

Цитата Сообщение от Vasyan Посмотреть сообщение
C#
1
MyClass c = new MyClass(); // с - это объект типа MyClass.
Нет.
с — это переменная типа MyClass, значением которой является ссылка на объект типа MyClass.
Именно так правильно говорить с точки зрения терминологии.

Цитата Сообщение от Vasyan Посмотреть сообщение
Но на уровне памяти,получается что "с"(это указатель)
с — это переменная, значение которой — ссылка на объект . Указатель — это совсем другое.

Цитата Сообщение от Vasyan Посмотреть сообщение
расположен в стеке
Местонахождение переменной — деталь реализации рантайма, она может находиться где угодно в зависимости от времени ее жизни: в стеке, в куче или в регистре.
Из одной строчки кода невозможно сказать, где именно она будет расположена.
Конкретно в Майкрософтовской реализации шарпа в стеке хранятся только несоптимизированные и незахваченные локальные переменные, которые не находятся в блоке-итераторе или асинхронном методе. Во всех остальных случаях переменная хранится в куче.
Другие реализации шарпа имеют полное право хранить переменные где угодно — спецификация языка это разрешает.

Цитата Сообщение от Vasyan Посмотреть сообщение
мы говорим что с это объект типа MyClass
Да, так часто говорят, но технически это неправильно, т.к. создает неверное представление о расположении сущностей в памяти.
Лучше сразу стараться использовать правильную терминологию, чтобы в будущем не было путаницы — как, например, в ваших вопросах выше.

Цитата Сообщение от Vasyan Посмотреть сообщение
но не переменная типа MyClass
Именно переменная типа MyClass.
Если MyClass — ссылочный тип, то значением переменной является либо ссылка на экземпляр типа MyClass или его наследников, либо null.
Если MyClass — значимый тип, то значением переменной является сам экземпляр.

Цитата Сообщение от Vasyan Посмотреть сообщение
т.е. в памяти стека(!)
Не обязательно(!) в памяти стека.

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

Цитата Сообщение от Vasyan Посмотреть сообщение
до конца не было понятно какое будет поведение,если придать значение Null внутри контекста метода .
Для начала давайте немного разберемся в терминологи:
  1. Переменная — это место для хранения информации
  2. Переменные есть двух типов: ссылочные и значимые
  3. Значеним переменной ссылочного типа является ссылка на экземпляр тпа, хранящийся где-то в другом месте, или null
  4. Значением переменной значимого типа является сам экземпляр типа.
  5. Переменная, объявленная в методе или вложенной области видимости, называется локальной.
  6. Переменная, объявленная в теле класса, называется полем класса.
  7. Переменная, объявленная в сигнатуре метода, называется параметром метода (значение, которое передается в метод в момент вызова называется аргументом).
  8. При присваивании, передаче в метод и возврате из метода создается копия значения переменной.
  9. При передаче в метод с параметрами ref/out передается сама переменная, но с другим именем.
  10. Из восьмого пункта следует, что при присваивании, передаче в метод или возврате из метода переменной ссылочного типа создается копия ссылки на тот же самый экземпляр.
  11. Из восьмого же пункта следует, что при присваивании, передаче в метод или возврате из метода переменной значимого типа создается копия экземпляра.

Если хорошо усвоить вышеприведенные пункты, то все непонятные моменты должны исчезнуть.

На предыдущих страницах есть несколько приблизительных иллюстраций с расположением и порядком создания значений в памяти.
Приблизительных — потому что там, в частности, явно разделены стек и куча, а разные реализации шарпа имеют право хранить переменные там, где им вздумается.
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
07.12.2016, 23:53
Цитата Сообщение от kolorotur Посмотреть сообщение
Нет.
с — это переменная типа MyClass, значением которой является ссылка на объект типа MyClass.
Именно так правильно говорить с точки зрения терминологии.
Не знаю,но даже сам Рихтер утверждает обратное.

Цитата Сообщение от kolorotur Посмотреть сообщение
с — это переменная, значение которой — ссылка на объект . Указатель — это совсем другое.
Понял,благодарю.
Тогда вопрос остается открытым. Что такое указатель и что такое ссылка в контексте управляемой памяти языка C#?

Цитата Сообщение от kolorotur Посмотреть сообщение
Местонахождение переменной — деталь реализации рантайма, она может находиться где угодно в зависимости от времени ее жизни: в стеке, в куче или в регистре.
Из одной строчки кода невозможно сказать, где именно она будет расположена.
Конкретно в Майкрософтовской реализации шарпа в стеке хранятся только несоптимизированные и незахваченные локальные переменные, которые не находятся в блоке-итераторе или асинхронном методе. Во всех остальных случаях переменная хранится в куче.
Другие реализации шарпа имеют полное право хранить переменные где угодно — спецификация языка это разрешает.
Вот тут если можно по подробнее?
Я в последнее время углубляюсь по теме "как CLR управляет\распределяется памятью".
Даже если взять ваши сообщение из этой темы(которые датируются 2012ом годом),или к примеру Рихтера,или кучу других в статьей,то можно увидеть одну закономерность(и иллюстрации в виде картинок),а именно:
ссылки ссылочного типа размещаются в стеке(!).

Странно,хотя вполне ожидаемо(в случае как и с жит-компиляторами,которые могут быть оптимизированы по разному,соответственно на выходе разный IL код,а как итог совсем другое поведение).

Цитата Сообщение от kolorotur Посмотреть сообщение
Да, так часто говорят, но технически это неправильно, т.к. создает неверное представление о расположении сущностей в памяти.
Лучше сразу стараться использовать правильную терминологию, чтобы в будущем не было путаницы — как, например, в ваших вопросах выше.
Зачем тогда сделали такую подмену понятий?
Цитата Сообщение от kolorotur Посмотреть сообщение
Именно переменная типа MyClass.
Если MyClass — ссылочный тип, то значением переменной является либо ссылка на экземпляр типа MyClass или его наследников, либо null.
Если MyClass — значимый тип, то значением переменной является сам экземпляр.
Это понятно,и тут вопросов не возникает.

Относительно переменной,получается что каждый раз нам нужно тянуть тонну слов(см. комментарий к коду ):
C#
1
2
3
4
5
6
7
8
class MyClass{}
....
static void Main()
{
//с это переменная(хранится либо в стеке(!) либо в куче(?) ),которая содержит в себе ссылку(адрес) на объект
// типа MyClass,который в своб очередь является ссылочным типом и расположен в Heap'e
MyClass c = new MyClass();
}
Как то не особо звучит

Цитата Сообщение от kolorotur Посмотреть сообщение
Не обязательно(!) в памяти стека.
Кому верить тогда?
И стоит ли вообще на этом заострять свое внимание?

Не по теме:

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



Цитата Сообщение от kolorotur Посмотреть сообщение
Не сочтите за оскорбление, но единственное, что верно в этой фразе — это то, что выделяется новая область памяти.
Ну я не знаю даже...Замените слово "указатель" на "ссылку",и вместо "работает с адресом" на "хранит в себе адрес оригинального объекта <КакойТоСсылочныйТип> расположенного в куче".
Т.е. перефразирую для вас
Цитата Сообщение от Vasyan
Правильнее сказать,что выделяется новая область памяти в стеке или куче(это уже решит CLR) для ссылки копии(которую мы передаем как параметр в метод),которая хранит в себе адрес оригинального объекта поля List(а он в свою очередь,из за своего ссылочного типа,явно расположен в управляемой куче).
Цитата Сообщение от kolorotur Посмотреть сообщение
Для начала давайте немного разберемся в терминологи:
Переменная — это место для хранения информации
Переменные есть двух типов: ссылочные и значимые
Значеним переменной ссылочного типа является ссылка на экземпляр тпа, хранящийся где-то в другом месте, или null
Значением переменной значимого типа является сам экземпляр типа.
Переменная, объявленная в методе или вложенной области видимости, называется локальной.
Переменная, объявленная в теле класса, называется полем класса.
Переменная, объявленная в сигнатуре метода, называется параметром метода (значение, которое передается в метод в момент вызова называется аргументом).
При присваивании, передаче в метод и возврате из метода создается копия значения переменной.
При передаче в метод с параметрами ref/out передается сама переменная, но с другим именем.
Из восьмого пункта следует, что при присваивании, передаче в метод или возврате из метода переменной ссылочного типа создается копия ссылки на тот же самый экземпляр.
Из восьмого же пункта следует, что при присваивании, передаче в метод или возврате из метода переменной значимого типа создается копия экземпляра.
Ну вы совсем обижаете .
Это и так понятно,за исключением момента с трактовкой объекта,то бишь что то уж вы сильно обостряете внимание на этом.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.12.2016, 00:57
Цитата Сообщение от Vasyan Посмотреть сообщение
даже сам Рихтер утверждает обратное.
Книжку в оригинале читаете? Как там написано?

Цитата Сообщение от Vasyan Посмотреть сообщение
Что такое указатель и что такое ссылка в контексте управляемой памяти языка C#?
Указатель — это адрес памяти. В шарпе указатели имеются в весьма ограниченном виде, доступны только при использовании небезопасного контекста.
Ссылка — это больше похоже на дескриптор, с помощью которого можно получить доступ к объекту.

Цитата Сообщение от Vasyan Посмотреть сообщение
ссылки ссылочного типа размещаются в стеке(!)
Не ссылки, а экземпляры, они же объекты. Ссылка — это значение переменной. Переменная может храниться где угодно.
По факту в майкрософтовской реализации шарпа экземпляры ссылочных типов всегда хранятся в куче. Вполне можно сделать оптимизацию, которая в некоторых случаях будет их держать и в куче, но эта оптимизация не реализована. Другие компиляторы могут реализовать такую оптимизацию, запрета нет.

Цитата Сообщение от Vasyan Посмотреть сообщение
Зачем тогда сделали такую подмену понятий?
Жаргон. Одно слово вместо нескольких.
Люди, знакомые с языком, в общении друг с другом прекрасно понимают о чем идет речь, а количество звуков экономится.
Проблемы начинают возникать тогда, когда эти люди начинают жаргон использовать в общении с теми, кто язык только еще изучает. Или, того хуже, начинают писать статьи/руководства/книги с использованием "словечек".
Можно серьезно запутаться.

Цитата Сообщение от Vasyan Посмотреть сообщение
получается что каждый раз нам нужно тянуть тонну слов
Собственно, потому и используют более короткие (хоть и неправильные) слова — для экономии

Цитата Сообщение от Vasyan Посмотреть сообщение
Как то не особо звучит
Да главное не произносить, а просто понимать — что там где и куда
Если постоянно использовать правильную терминологию, то разумеется можно язык сломать. Именно поэтому в любой профессии и существует такая штука, как профессиональный жаргон.

Цитата Сообщение от Vasyan Посмотреть сообщение
Кому верить тогда?
Не верьте никому!
Возьмите да протестируйте всё сами — это закаляет характер

Цитата Сообщение от Vasyan Посмотреть сообщение
И стоит ли вообще на этом заострять свое внимание?
Знать — полезно, легче избежать некоторых паскудных багов.
Зацикливаться — я думаю не стоит, если вы не хотите написать свой собственный компилятор.
Огромное количество людей потратило много времени, реализуя сборщик мусора, — именно для того, чтобы вы себе не забивали голову местоположнием и временем жизни объектов.

Цитата Сообщение от Vasyan Посмотреть сообщение
может привести вам ряд статей(ссылки и отсылки к книгам,где авторы яро и смело бьют себе в грудь и уверяют,мол ссылки ссылочного типа хранятся в стеке)
Интересно было бы глянуть.
Но только перед тем, как приводить статьи, прочитайте те абзацы по-внимательнее: возможно, речь там все-таки идет об экземплярах ссылочных типов, а не о ссылках на них.

Цитата Сообщение от Vasyan Посмотреть сообщение
Замените слово "указатель" на "ссылку",и вместо "работает с адресом" на "хранит в себе адрес оригинального объекта <КакойТоСсылочныйТип> расположенного в куче".
Указатель — это просто адрес виртуальной памяти процесса. Всё. Он может указывать в произвольное место в памяти.
Ссылка — это всегда либо валидный дескриптор объекта, либо null. Их важно различать, особенно в шарпе, т.к. там есть и сылки, и указатели.
То есть ссылка — это абстракция, некая сущность, с помощью которой получается доступ к объекту.
Скажу по секрету: в шарпе ссылки реализованы через обычные указатели, но с определенными жесткими ограничениями. Например, ссылка не может ссылаться на часть объекта.
Но то, что ссылки в шарпе реализованы через указатели — это опять же деталь реализации. Какой-нибудь Mono/Xamarin имеет полное право реализовать ссылки через самые настоящие дескрипторы.

Есть такое выражение, что если что-то выглядит как утка и крякает как утка, то это утка.
Вот это выражение можно перефразировать и для ссылок в шарпе: ссылкой называется сущность, которая имеет поведение и все свойства ссылки согласно спецификации языка. Я весь списк сходу не припомню, но два важных пункта — это всегда известен статический тип (даже для null) и если ссыла не null, то статический тип ссылки всегда совместим с фактическим типом объета, на который она ссылается.
Говоря проще, если ссылка имеет определенный тип, то и ссылаться она может только на этот же тип или его наследников. Это ограничение отсутствует для указателей.

Цитата Сообщение от Vasyan Посмотреть сообщение
Ну вы совсем обижаете
Обижать цели не стояло. Если чем-то задел — приношу извинения.

Цитата Сообщение от Vasyan Посмотреть сообщение
за исключением момента с трактовкой объекта,то бишь что то уж вы сильно обостряете внимание на этом.
В смысле?
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
08.12.2016, 01:46
Цитата Сообщение от kolorotur Посмотреть сообщение
Книжку в оригинале читаете? Как там написано?
в переводе.
Цитата Сообщение от kolorotur Посмотреть сообщение
Ссылка — это больше похоже на дескриптор, с помощью которого можно получить доступ к объекту.
Так ведь эта ссылка хранит в себе значение(адрес) объекта,на который ссылается то?(Или все таки нет)

Цитата Сообщение от kolorotur Посмотреть сообщение
Не ссылки, а экземпляры, они же объекты. Ссылка — это значение переменной. Переменная может храниться где угодно.

нет,именно "ссылки" или как вы их называете "переменные",расположены в стеке,а сам объект и тип объекта в куче(про что я писал выше).

C#
1
2
3
4
5
6
7
class MyClass{}
...
static void Main()
{
   MyClass c = new MyClass();
  
}
А вот и моя иллюстрация:
[image]https://www.cyberforum.ru/attachments/771016d1481149908[/image]

Цитата Сообщение от kolorotur Посмотреть сообщение
Но только перед тем, как приводить статьи, прочитайте те абзацы по-внимательнее: возможно, речь там все-таки идет об экземплярах ссылочных типов, а не о ссылках на них.
Нет,именно ссылки(переменные) на ссылочные объекты(экземпляры типа reference type).

Статья 1
Статья 2
Статья 3
Статья 4
Ну и у Рихтера в 4 главе есть нечто подобное .

Цитата Сообщение от kolorotur Посмотреть сообщение
Скажу по секрету: в шарпе ссылки реализованы через обычные указатели, но с определенными жесткими ограничениями. Например, ссылка не может ссылаться на часть объекта.
Значит ссылки хранят адрес на сам объект?(это определение верно?)
Миниатюры
Как применить ref и out для ссылок на объекты  
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.12.2016, 02:33
Цитата Сообщение от Vasyan Посмотреть сообщение
в переводе.
Рихтер — серьезный автор, потому либо вы что-то не так поняли, либо кривой перевод. Ну или очередное использование жаргонов.

Цитата Сообщение от Vasyan Посмотреть сообщение
Так ведь эта ссылка хранит в себе значение(адрес) объекта,на который ссылается то?(Или все таки нет)
В майкросовтовской реализации компилятора и рантайма — да. Но в следующей версии фреймворка может всё поменяться — это свойство детали реализации.
Почему вам интересно, каким образом реализованы ссылки?

Цитата Сообщение от Vasyan Посмотреть сообщение
именно "ссылки" или как вы их называете "переменные"
Я не называю ссыкли переменными
Ссылка — это значение, переменная — это хранилище.
Значение переменной ссылочного типа — ссылка.
Проводя аналогию, переменная — шкатулка, а ссылка — это листочек с указанем где найти то, что вам нужно, хранящийся в этой шкатулке.

Цитата Сообщение от Vasyan Посмотреть сообщение
расположены в стеке,а сам объект и тип объекта в куче
Это неверно.
Особенно если учесть, что поле класса — это тоже переменная.

Цитата Сообщение от Vasyan Посмотреть сообщение
Статья 1
Все типы значений являются производными от типа System.ValueType и размещают свое значение в стеке.
Это неправда.

Цитата Сообщение от Vasyan Посмотреть сообщение
Статья 2
Здесь автор более аккуратен:
Value Types and Pointers always go where they were declared. [...]Now, Value Types are also sometimes placed on the Heap.
Хотя тоже дает не полную картину.

Цитата Сообщение от Vasyan Посмотреть сообщение
Статья 3
Ближе к истине, если в первой строчке заменить always на sometimes:
The stack is always used to store the following two things:
The reference portion of reference-typed local variables and parameters (such as the myTextBox reference)
Value-typed local variables and method parameters (structs, as well as integers, bools, chars, DateTimes, etc.)
The following data is stored on the heap:
The content of reference-type objects.
Anything structured inside a reference-type object.
Цитата Сообщение от Vasyan Посмотреть сообщение
Статья 4
Автор рубит с плеча:
Reference Type variables are stored in the heap while Value Type variables are stored in the stack.
Хотелось бы поинтересоваться у автора: как быть с переменными значимых типов, объявленными в методе-итераторе или в асинхронном методе? В каком именно стеке они хранятся и каким образом? Особенно интересно узнать про асинхронные методы: в стеке какого именно потока они хранятся?

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

Цитата Сообщение от Vasyan Посмотреть сообщение
у Рихтера в 4 главе есть нечто подобное
CLR via C#?
Value type instances are usually allocated on a thread’s stack (although they can also be embedded as a field in a reference type object).
Ключевое слово — usually.

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

Обращаю внимание: речь идет о переменных, а не об экземплярах типа.
Экземпляры ссылочных типов всегда создаются в куче (в М-й реализации языка). Экземпляры значимых типов — там, где создается сама переменная, т.к. экземпляр хранится в переменной.

Цитата Сообщение от Vasyan Посмотреть сообщение
Значит ссылки хранят адрес на сам объект? это определение верно?
То, каким способом реализованы ссылки — compiler-specific, то есть спецификацией языка не определено и каждый компилятор/рантайм может реализовывать их как угодно.
Потому ответом на этот вопрос может быть только встречный вопрос: о каком компиляторе какой версии идет речь?
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
08.12.2016, 03:08
Цитата Сообщение от kolorotur Посмотреть сообщение
Рихтер — серьезный автор, потому либо вы что-то не так поняли, либо кривой перевод. Ну или очередное использование жаргонов.
Возможно. Но в 4ой главе показан пример(с картинками),который мы обсуждаем. И откровенно говоря,я не замечал,чтобы автор(Рихтер) писал что то вроде : иногда переменные ссылочного типа хранятся в куче.
Отсюда и конфуз у меня .
Цитата Сообщение от kolorotur Посмотреть сообщение
В майкросовтовской реализации компилятора и рантайма — да. Но в следующей версии фреймворка может всё поменяться — это свойство детали реализации.
Почему вам интересно, каким образом реализованы ссылки?
Потому что многие(те же статьи) об этом пишут,и хочется иметь правильное представление.
Цитата Сообщение от kolorotur Посмотреть сообщение
Я не называю ссыкли переменными
Ссылка — это значение, переменная — это хранилище.
Значение переменной ссылочного типа — ссылка.
Да,это и имелось виду,т.е. подразумевается,что ссылка это и есть переменная,которая хранит в себе эту самую ссылку(значение,аля адрес на который ссылается).
Цитата Сообщение от kolorotur Посмотреть сообщение
Проводя аналогию, переменная — шкатулка, а ссылка — это листочек с указанем где найти то, что вам нужно, хранящийся в этой шкатулке.
Может все таки шкатулка это объект,а переменная это листочек,на котором указана дорога(ссылка,то бишь значение,то бишь адрес) к шкатулке(экземпляру объекта) ?
Цитата Сообщение от kolorotur Посмотреть сообщение
Особенно если учесть, что поле класса — это тоже переменная.
Поля Value Type объявленные в классе,на сколько мне известно аллоцириуются в Heap'e.

Цитата Сообщение от kolorotur Посмотреть сообщение
Это неправда.
Ну здесь автор просто не договорил. System.ValueType неявно унаследован от System.Object, благодаря чему у пользовательских структур,есть методы Equals(),ToString(),GetHashCode() - которые так же можно переопределить(это исключение сделанное для структур,ибо полиморфизм для них запрещен).
Цитата Сообщение от kolorotur Посмотреть сообщение
Хотя тоже дает не полную картину.
Да,но мы то с вами говорим исключительно об типе reference type.

Цитата Сообщение от kolorotur Посмотреть сообщение
CLR via C#?
Он самый (.NET 4.5 C# 5.0, 2013ый год)
Цитата Сообщение от kolorotur Посмотреть сообщение
Ключевое слово — usually
Да,но опять же,речь только об Reference Type.

Цитата Сообщение от kolorotur Посмотреть сообщение
В шарпе есть два типа памяти: долговременная и кратковременная. Долговременная — это куча, управляемая и неуправляемая
Да,про это слышал про Small Object Heap / Large Object Heap, вот хорошая статья на хабре


Цитата Сообщение от kolorotur Посмотреть сообщение
То, каким способом реализованы ссылки — compiler-specific, то есть спецификацией языка не определено и каждый компилятор/рантайм может реализовывать их как угодно.
Потому ответом на этот вопрос может быть только встречный вопрос: о каком компиляторе какой версии идет речь?
Я понял вас,благодарю за эту информацию.

В общем посыл понял. И как вы описали ранее(сообщение датируемым 2012ым годом), и моя иллюстрация(она очень похоже на ту,что у Рихтера),имеет место быть,но только как случай(то бишь не всегда).
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.12.2016, 03:14
Цитата Сообщение от Vasyan Посмотреть сообщение
Может все таки
Нет, именно так, как я написал.
Переменная — это просто хранилище информации, в котором может лежать какое-нибудь значение.
Одно из возможных значений — ссылка на экземпляр объекта.

Цитата Сообщение от Vasyan Посмотреть сообщение
Поля Value Type объявленные в классе,на сколько мне известно аллоцириуются в Heap'e.
Совершенно верно.
Как видите, уже один этот факт опровергает всех любителей рассказать о том, что значимые типы всегда живут в стеке.

Цитата Сообщение от Vasyan Посмотреть сообщение
System.ValueType неявно унаследован от System.Object, благодаря чему у пользовательских структур,есть методы Equals(),ToString(),GetHashCode() - которые так же можно переопределить(это исключение сделанное для структур,ибо полиморфизм для них запрещен).
Верно, только как это относится к обсуждаемой теме?

Цитата Сообщение от Vasyan Посмотреть сообщение
мы то с вами говорим исключительно об типа reference type.
А я думал мы говорим о переменных, неважно какого типа
Ведь ref/out — это про переменные, а не про экземпляры.

Цитата Сообщение от Vasyan Посмотреть сообщение
Он самый (.NET 4.5 C# 5.0, 2013ый год)
У меня старенькая версия, но с тех пор ничего не поменялось, разве что асинхронные методы добавились.

Цитата Сообщение от Vasyan Посмотреть сообщение
опять же,речь только об Reference Type.
Простите, я не понимаю.
У вас же вопросы возникли по поводу ref/out, так?

Цитата Сообщение от Vasyan Посмотреть сообщение
Small Object Heap / Large Object Heap
Они обе входят в категорию управляемой памяти.

Цитата Сообщение от Vasyan Посмотреть сообщение
Я понял вас
Я это лишь к тому, что то, как реализованы ссылки — настолько дремучая деталь реализации, что толку от этого знания мало.
Если все-таки интересно, то в майкрософтовской версии шарпа объекты ссылочных типов реализованы как блоки памяти, первые байты которых, т.н. заголовки, хранят определенные метаданные об экземпляре (ссылку на тип, блок синхронизации и т.д.).
Ссылка на такой объект реализована как указатель на этот заголовок.
0
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
08.12.2016, 17:50
Цитата Сообщение от kolorotur Посмотреть сообщение
Потому ответом на этот вопрос может быть только встречный вопрос: о каком компиляторе какой версии идет речь?
К примеру RyuJIT
Цитата Сообщение от kolorotur Посмотреть сообщение
Совершенно верно.
Как видите, уже один этот факт опровергает всех любителей рассказать о том, что значимые типы всегда живут в стеке.
О чем речь?
Разве я утверждал,что ValueType хранятся всегда и только всегда в стеке?

Я вам даже больше скажу,в каких именно случаях ValueType хранится в Хипе:
1. Если ValueType упакован(boxed) - хранится в хипе
2. Если ValueType являются полем класса - хранится в хипе
3. В случае замыкания с анонимными методами(а мы ведь знаем,что при Closure,компилятор ретранслирует код в доп. класс,где переменная становится полем,отсюда по логике пункт №2) - хранится в хипе
4. Если находится в блоке итератора(yield,который разворачивает класс с интерфейсом IEnumerable) - хранится в хипе

Цитата Сообщение от kolorotur Посмотреть сообщение
Верно, только как это относится к обсуждаемой теме?
Это к слову.

Цитата Сообщение от kolorotur Посмотреть сообщение
А я думал мы говорим о переменных, неважно какого типа
Ведь ref/out — это про переменные, а не про экземпляры.
Нет конечно!
Речь шла исключительно только об ReferenceType , т.к. не было понятно мне,какое поведение получает ReferenceType в контексте метода,если придать значение Null.
Заметьте,я ведь ни слова не говорил об ValueType в моих сообщениях.

Цитата Сообщение от kolorotur Посмотреть сообщение
Простите, я не понимаю.
У вас же вопросы возникли по поводу ref/out, так?
ReferenceType и только,ибо поведение ValueType(и где они хранятся),мне ясно.
Цитата Сообщение от kolorotur Посмотреть сообщение
Если все-таки интересно, то в майкрософтовской версии шарпа объекты ссылочных типов реализованы как блоки памяти, первые байты которых, т.н. заголовки, хранят определенные метаданные об экземпляре (ссылку на тип, блок синхронизации и т.д.).
и получается что ValueType,которые хранятся в хипе,имеют такие же заголовки,в виде блока синхронизации и тд,как и ReferenceType
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
08.12.2016, 20:40
Цитата Сообщение от Vasyan Посмотреть сообщение
К примеру RyuJIT
Не знаком — ничего сказать не могу

Цитата Сообщение от Vasyan Посмотреть сообщение
Разве я утверждал,что ValueType хранятся всегда и только всегда в стеке?
Ну я же выше написал, что это про любителей рассказать, что значимые типы вегда в стеке.
Вы вроде бы такого не говорили.

Цитата Сообщение от Vasyan Посмотреть сообщение
Я вам даже больше скажу,в каких именно случаях ValueType хранится в Хипе:
Я же выше об этом писал.
Добавьте еще асинхронные методы пятым пунктом.

Цитата Сообщение от Vasyan Посмотреть сообщение
Речь шла исключительно только об ReferenceType , т.к. не было понятно мне,какое поведение получает ReferenceType в контексте метода,если придать значение Null.
Так именно для понимания того, что происходит в этом контексте, я и написал выше как работают переменные. А вы в ответ обиделись.

Цитата Сообщение от Vasyan Посмотреть сообщение
получается что ValueType,которые хранятся в хипе,имеют такие же заголовки,в виде блока синхронизации и тд,как и ReferenceType
Нет конечно. Заголовок имеет объект, полем которого является ValueType.
1
 Аватар для Vasyan
3 / 3 / 1
Регистрация: 21.04.2012
Сообщений: 76
08.12.2016, 22:37
Цитата Сообщение от kolorotur Посмотреть сообщение
ак именно для понимания того, что происходит в этом контексте, я и написал выше как работают переменные. А вы в ответ обиделись.
Я не обиделся,все в порядке , видимо мы друг друга не поняли,и обсуждали "более" глобально. Но опять же,вопрос стоял о ReferenceType.
Цитата Сообщение от kolorotur Посмотреть сообщение
Нет конечно. Заголовок имеет объект, полем которого является ValueType.
Вы правы,тут я глупость ляпнул.

Цитата Сообщение от kolorotur Посмотреть сообщение
Добавьте еще асинхронные методы пятым пунктом.
это по сути и есть пункт по типу с замыканием(Closure).

В общем благодарю за быстрые ответы.
1
 Аватар для Enflamed
3 / 3 / 1
Регистрация: 12.04.2015
Сообщений: 74
17.12.2016, 02:41
Добрый день, я сторонний наблюдатель, тему прочитал целиком.

Цитата Сообщение от kolorotur Посмотреть сообщение
ссылки в шарпе реализованы через указатели
Я лично вообще всегда считал, экземпляр класса - это указатель на класс и только поэтому мы можем можем присвоить ссылочному типу null, по аналогии с nullptr (или какое там значение советуют присваивать в C++ указателю, который больше не будет использоваться).

И, соответственно, я считал, что при передаче (из main, например) в метод ссылочного типа создаётся копия указателя на экземпляр класса.
Соответственно, мы можем изменять этот указатель, чтобы он указывал на что-нибудь другое, а исходный указатель и то, на что он указывает остаются без изменений, верно?

Вопрос небольшой, с Вашего позволения, kolorotur, ответьте, пожалуйста:

Если при передаче ValueType (ref int index) с модификатором ref у нас должна передаваться ссылка на область памяти, содержащая нашу переменную index, то при каждой передаче этой ссылки (ref int index) в метод, будет ли у нас будет создаваться дополнительный указатель, содержащий значение этой области памяти или же в метод будет передаваться лишь сама ссылка? Другими словами, является ли на низком уровне передача значимого типа по ссылке передачей по ссылке или по сути является передачей с созданием нового указателя?

(Меня это интересует в контексте затрат памяти на указатели при передаче значимого типа по ссылке множество раз во вложенные вызовы различных методов)
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
17.12.2016, 04:29
Цитата Сообщение от Enflamed Посмотреть сообщение
является ли на низком уровне передача значимого типа по ссылке передачей по ссылке или по сути является передачей с созданием нового указателя?
На самом низком уровне все зависит от того, какой промежуточный код сгенерирует компилятор.
В худшем случае будет создаваться указатель на переменную при каждом вызове.

Цитата Сообщение от Enflamed Посмотреть сообщение
Меня это интересует в контексте затрат памяти на указатели при передаче значимого типа по ссылке множество раз во вложенные вызовы различных методов
Да бросьте, какие там затраты — один указатель? Это 32/64 бита, чепуха.
Единственная "проблема", которую может создать дополнительный указатель — это взорванный стек при длинной цепочке вызовов, но если у вас столько вызовов, что стек взрывается из-за локальной переменной в 32/64 бита, то проблема кроется уже не в наличии указателя, а в наличии такой глубины вызовов.
0
 Аватар для Enflamed
3 / 3 / 1
Регистрация: 12.04.2015
Сообщений: 74
17.12.2016, 06:03
Заранее, извиняюсь за оффтоп (Если мой вопрос можно счесть оффтопом)

Цитата Сообщение от kolorotur Посмотреть сообщение
Да бросьте, какие там затраты — один указатель? Это 32/64 бита, чепуха.
У меня просто сейчас есть проект по созданию структуры (дерева) рекурсивно из строки символов (парсер) -> я в каждый конструктор элемента дерева передаю значение индекса последнего пропаршенного символа...

Просто интересно, будет ли выделяться каждый раз память под этот указатель (или ссылку) "ref"?

(Если в случае с C++ мы точно знаем, что для параметра (&index) лишних операций по выделению памяти не происходит)
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
17.12.2016, 17:23
Цитата Сообщение от Enflamed Посмотреть сообщение
интересно, будет ли выделяться каждый раз память под этот указатель (или ссылку) "ref"?
Зависит целиком от компилятора. Спецификация языка определяет только поведение, которое должно наблюдаться при использовании определенных языковых конструкций. Как это поведение реализовано — полностью отдается на откуп компилятору и среде выполнения.
Конкретно в майкрософтовской реализации компилятора под настольную версию Windows просто создается параметр-адрес, как в плюсах.
Было:
C#
1
void Foo(ref int arg)
Стало:
C++
1
void Foo(int &arg)
Другие компиляторы могут это реализовать как-то иначе. Например, создавая указатель.

Цитата Сообщение от Enflamed Посмотреть сообщение
я в каждый конструктор элемента дерева передаю значение индекса последнего пропаршенного символа
И добавляете параметру ref только для того, чтобы избежать выделения дополнительной памяти под локальную переменную?
Лучше так не делайте, поскольку ключевое слово ref ничего не говорит об используемой памяти, у него ровно одно семантическое значение: передача переменной по ссылке.
Лучше все-таки не строить логику приложения, опираясь на детали реализации компилятора или среды выполнения — в истории огромная масса примеров, когда написанное подобным образом приложение просто переставало работать при выходе очередного обновления или при переходе на новую версию ОС. А виновата, как всегда, "тупая винда"
0
 Аватар для Enflamed
3 / 3 / 1
Регистрация: 12.04.2015
Сообщений: 74
18.12.2016, 00:02
Цитата Сообщение от kolorotur Посмотреть сообщение
Лучше все-таки не строить логику приложения, опираясь на детали реализации компилятора или среды выполнения
Да, действительно, я уже всё пределал, просто вынес параметр во внешнюю переменную, не знаю какой индус мне в голову залез когда я продумывал логику
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.12.2016, 00:02

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

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


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

Или воспользуйтесь поиском по форуму:
57
Ответ Создать тему
Новые блоги и статьи
У нас сейчас поговорку "Опять 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 Я говорю, что Время- как вода течет. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru