Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вопросы по С#, возникшие в ходе изучения  (Прочитано 13977 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dmitry
Помогающий

ru
Offline Offline

« : 22-10-2009 15:11 » 

Привет всем,
Изучаю шарп, в этой теме буду задавать некоторые вопросы, а вы по возможности пытайтесь на них отвечать.  Ага


Вот такая конструкция работает
object obj = ....
int? my = obj as int?;

Почему мы не можем распаковать так?
int? my = obj as int;
Да, по требованиям компилятора оба операнда должны быть ссылочными или nullable типами.  Но ведь тут всё замечательно - если в obj было упаковано число, int неявно приводится к Nullable<int>,  иначе ему присваивается null.


Хм, можно так:

int myInt = 100;
object obj = myInt;
int? my = obj as int?;


Сообщения не правятся... монолог будет.
Т.е. получается, что как бы тип int - производный от nullable<int> (и вообще приводить int к int? можно неявно) . Но ведь это структуры, для них нет наследования?
« Последнее редактирование: 22-10-2009 16:00 от RXL » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 22-10-2009 17:46 » 

Цитата: Dmitry
Почему мы не можем распаковать так?
int? my = obj as int;
Оператор as использует RTTI для определения типа значения, хранящегося в переменной (возможно, другого, более общего типа). Для value-типов RTTI отсутствует, поэтому оператор работать не может.

P.S. А вообще, как говорится, "потому что гладиолус!" Улыбаюсь Раз нельзя так использовать оператор, значит нельзя.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #2 : 22-10-2009 18:22 » 

Оператор as использует RTTI для определения типа значения, хранящегося в переменной (возможно, другого, более общего типа). Для value-типов RTTI отсутствует, поэтому оператор работать не может.
А как же тогда
Код:
int a = 1;
a.GetType();

В общем, я понял. Оператор as возвращает тип второго операнда. Естественно, он должен поддерживать null-значение.

RXL, странный ход. По-моему, гораздо чаще новички не могут с первого раза толково сформулировать вопрос, и пытаются отыскать кнопку редактирования.  Ага
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 22-10-2009 20:03 » 

GetType возвращает объект типа Type, описывающий некий тип. Относится ли этот тип к переменной или к хранящемуся в ней значению, прямо зависит от наличия или отсутствия RTTI.

Цитата: Dmitry
В общем, я понял. Оператор as возвращает тип второго операнда.
Оператор as возвращает не тип, а значение, тип которого сводится (или соответствует) заданному, либо null, если соответствие отсутствует. Тип возвращает GetType.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #4 : 22-10-2009 20:35 » 

Оператор as возвращает не тип, а значение, тип которого сводится (или соответствует) заданному, либо null, если соответствие отсутствует.
Да, я это и имел в виду, неправильно написал. Конечно, as не Type возвращает. В случае, если соответствие отсутствует, возвращается тоже значение заданного типа, но оно равно null. Поэтому "int? my = obj as int" и не работает - значению типа int нельзя присвоить null, а вот int? - можно.

Из мсдн:
expression as type
эквивалентно
expression is type ? (type)expression : (type)null
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 22-10-2009 21:16 » 

RXL, странный ход. По-моему, гораздо чаще новички не могут с первого раза толково сформулировать вопрос, и пытаются отыскать кнопку редактирования.  Ага
Offtopic:

Как говорится - поадминь с мое...
Кривизну может отредактировать модератор, а стертое может не остаться даже в бекапах.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dmitry
Помогающий

ru
Offline Offline

« Ответ #6 : 27-10-2009 06:58 » 

Перешёл на Рихтера, до этого читал сначала Троелсена, потом  Нейгела и Ко. Жалею, что сразу с Рихтера не начал. У него хоть и основы, но гораздо толковее написано.
Пока вопрос остался - как CLR определяет связь между производными типами? В объектах-типах, которые хранят информацию о типах, об этом же нет никаких данных?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 27-10-2009 08:28 » 

Цитата: Dmitry
Пока вопрос остался - как CLR определяет связь между производными типами?
См. в сторону System.Reflections.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #8 : 28-10-2009 07:31 » 

См. в сторону System.Reflections.
Свойство типа BaseType возвращает базовый тип. Но мне интересно, как это реализовано. Подозреваю, что через метаданные.
 Ещё интересно, как определяется тип ссылки, через которую мы вызываем невиртуальный метод. Если метод виртуальный то цепочка действий более менее понятна - разыменовывание указателя, получение через указатель на объект-тип объекта Type, который и содержит таблицу методов.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 28-10-2009 08:51 » 

Цитата: Dmitry
Свойство типа BaseType возвращает базовый тип. Но мне интересно, как это реализовано.
Вопрос совершенно непонятный. Связь между классами определяет компилятор в процессе компиляции. Ты хочешь узнать, как реализован компилятор?

Что ты подразумеваешь под "метаданными", и почему тебе становится легче, когда ты начинаешь подозревать именно их? Улыбаюсь

Цитата: Dmitry
Ещё интересно, как определяется тип ссылки, через которую мы вызываем невиртуальный метод. Если метод виртуальный то цепочка действий более менее понятна - разыменовывание указателя, получение через указатель на объект-тип объекта Type, который и содержит таблицу методов.
Белые люди так не делают. В runtime для собственных внутренних нужд механизм reflections не используется, так как очень медленный. Компилятор для объекта создаёт таблицу виртуальных методов, в которой хранятся указатели на виртуальные методы. Когда класс унаследован от другого, в процессе создания объекта сначала срабатывает конструктор (по умолчанию, если не задан программистом явно) базового класса, который заполняет таблицу для базового класса, затем конструктор производного класса перезаписывает указатели на те методы, которые переопределены в нём самом.

В результате при обращении к объекту через переменную любого класса (хоть базового, хоть производного) всё равно вызываются методы производного класса.

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

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dmitry
Помогающий

ru
Offline Offline

« Ответ #10 : 29-10-2009 06:35 » 

Вопрос совершенно непонятный. Связь между классами определяет компилятор в процессе компиляции. Ты хочешь узнать, как реализован компилятор?
Да, что-то меня не туда повело Улыбаюсь Во время выполнения программы ведь по сути не существует никаких классов. Для невиртуальных методов компилятор на основании типа переменной, через которую мы делаем вызов, встраивает в код вызов конкретной функции.
 По поводу виртуальных методов. То, что я описал - написано у Рихтера. Что каждый объект в куче дополняется указателем на объект-тип и индексом для синхронизации. Объект-тип представляет собой данные о типе (классе), статические поля, таблицу методов. Я правильно теперь понял - этот объект-тип есть экземпляр класса Type (точнее Runtimetype, но сейчас это не важно), ссылку на который можно получить ч-з GetType или typeof,  и используется он только в рефлексии и для RTTI. А при вызове виртуальных методов используется скрытый указатель (который есть в объекте каждого класса, реализующего виртуальные методы) на таблицу в.м. Примерно так?

У тебя странно написано, что таблица в.м. заполняется конструкторами. Разве она не заполняется полностью для каждого класса компилятором?
« Последнее редактирование: 29-10-2009 09:01 от Dmitry » Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 29-10-2009 15:13 » new

Цитата: Dmitry
То, что я описал - написано у Рихтера. Что каждый объект в куче дополняется указателем на объект-тип и индексом для синхронизации. Объект-тип представляет собой данные о типе (классе), статические поля, таблицу методов. Я правильно теперь понял - этот объект-тип есть экземпляр класса Type (точнее Runtimetype, но сейчас это не важно), ссылку на который можно получить ч-з GetType или typeof,  и используется он только в рефлексии и для RTTI. А при вызове виртуальных методов используется скрытый указатель (который есть в объекте каждого класса, реализующего виртуальные методы) на таблицу в.м. Примерно так?

У тебя странно написано, что таблица в.м. заполняется конструкторами. Разве она не заполняется полностью для каждого класса компилятором?
То, что я сказал, относится не к .NET и C#. Это общий принцип работы виртуальных методов. Лично меня тонкости реализации этого принципа в .NET не интересовали и не интересуют. Суть состоит в том, что при позднем связывании у объекта есть таблица виртуальных методов, из которой он извлекает нужный метод. Заполняет ли её компилятор в точке создания объекта, или она вычисляется в runtime - для меня дело десятое.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines