Re[13]: Базовый вопрос по наследованию
От: MozgC США http://nightcoder.livejournal.com
Дата: 06.02.11 11:24
Оценка: +1
Здравствуйте, Jolly Roger, Вы писали:

JR>С другой стороны, тут есть ещё один момент, который я прошлой ночью упустил — рефлексия. (Ну очень спать хотелось ) Для неё необходимо, чтобы информация о всех членах класса, в том числе невиртуальных методах, была доступна в рантайм. В принципе, JIT может ей воспользоваться при необходимости. Но с другой стороны, ей-же может воспользоваться и C# компилятор, то есть такие вопросы можно вроде как разрешить на этапе компиляции в IL. Иначе у меня не получается непротиворечиво объяснить тот листинг, что я приводил здесь
Автор: Jolly Roger
Дата: 05.02.11
. Ведь в методе Test нет никаких упоминаний BaseObj, однако в IL-листинге он присутствует. Это, по-моему, может означать только одно — C#-компилятор произвёл поиск метода вверх по иерархии и подставил в результирующий IL код его адрес, этот адрес мы и видим в виде метки BaseObj::Sum. Иначе у меня как-то не срастается


Я так понимаю, что компилятор и JIT-работают вместе. Компилятор может в такой ситуации определить метод какого класса будет вызван, но у JIT'а есть фукнции дополнительной проверки и разрешения конфликтных ситуаций. Samius вчера высказал мнение, что это сделано потому, что IL в принципе может быть кривым, ведь нет гарантий, что он не был создан вручную или каким-то другим компилятором, поэтому JIT должен делать свои проверки и по-возможности разруливать "косяки".

JR>А вот тот пример с дизассемблированием, правкой и повторной компиляцией с помощью ILasm — а что покажет ILDasm, если ему скормить результат работы ILAsm? Там сохранится внесённое вручную Employee::GetYearsEmployed, или опять оказывается исходная EmployeeBase::GetYearsEmployed?


Ну, я же это написал в том свое посте:

Компилируем с помощью ILAsm.

Проверяем в ILDasm или Reflector'е:

    L_0000: nop 
    L_0001: newobj instance void JitTest.Program/Manager::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: callvirt instance int32 JitTest.Program/Employee::GetYearsEmployed()


Т.е. проверяем именно скомпилированную ILAsm'ом сборку.
Re[14]: Базовый вопрос по наследованию
От: MozgC США http://nightcoder.livejournal.com
Дата: 06.02.11 11:29
Оценка:
Здравствуйте, vf, Вы писали:

vf>Судя повсему тот класс который указан в IL предназначен только для пользователя, для компилятора он не нужен и не несет никакой информации.


Для JIT'а судя по всему все-таки нужен
Автор: MozgC
Дата: 06.02.11
.

vf>То есть тип объекта, JIT-компилятору (как параметр) не нужен, он его смотрит по obj.


См. выше.
Re[14]: Базовый вопрос по наследованию
От: vf  
Дата: 06.02.11 11:33
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>В таком случае без перекомпиляции вызовется метод базового класса. Видимо jit просто берет метод указанный в IL и, если он не найден в указанном классе, то идет вверх и ищет где он. А в данном примере в IL останется вызов базового класса, jit увидит, что метод есть у указанного класса и не проверит, что метод уже переопределен в дочернем.


Похоже что, все таки отработает как положено, лениво проверять

Вот здесь
Автор: vf
Дата: 06.02.11
, по мотивам первоисточника, я выразил свою мысль: что тип указаный в IL-коде после дисассемблера носит только информационный характер, и предназначен только для пользователя.
Re[15]: Базовый вопрос по наследованию
От: vf  
Дата: 06.02.11 11:36
Оценка:
Здравствуйте, MozgC, Вы писали:

vf>>Судя повсему тот класс который указан в IL предназначен только для пользователя, для компилятора он не нужен и не несет никакой информации.


MC>Для JIT'а судя по всему все-таки нужен
Автор: MozgC
Дата: 06.02.11
.


А зачем? Вся информация о типе объекта у него есть в рантайме.
Re[15]: Базовый вопрос по наследованию
От: MozgC США http://nightcoder.livejournal.com
Дата: 06.02.11 11:46
Оценка:
Здравствуйте, vf, Вы писали:

MC>>В таком случае без перекомпиляции вызовется метод базового класса. Видимо jit просто берет метод указанный в IL и, если он не найден в указанном классе, то идет вверх и ищет где он. А в данном примере в IL останется вызов базового класса, jit увидит, что метод есть у указанного класса и не проверит, что метод уже переопределен в дочернем.


vf>Похоже что, все таки отработает как положено, лениво проверять


Я написал, как отработает. Это не мои фантазии
Re[16]: Базовый вопрос по наследованию
От: vf  
Дата: 06.02.11 12:00
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Я написал, как отработает. Это не мои фантазии


Да, действительно.
Re[16]: Базовый вопрос по наследованию
От: vf  
Дата: 06.02.11 12:07
Оценка:
Здравствуйте, MozgC, Вы писали:

Покоя нет мне... как же так, выходит что здесь ошибка в описании?! Или я не правильно понял?

That is, the method is chosen based on the runtime type of obj rather than the compile-time class visible in the method pointer.

Re[14]: Базовый вопрос по наследованию
От: Jolly Roger  
Дата: 06.02.11 12:19
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Я так понимаю, что компилятор и JIT-работают вместе. Компилятор может в такой ситуации определить метод какого класса будет вызван, но у JIT'а есть фукнции дополнительной проверки и разрешения конфликтных ситуаций. Samius вчера высказал мнение, что это сделано потому, что IL в принципе может быть кривым, ведь нет гарантий, что он не был создан вручную или каким-то другим компилятором, поэтому JIT должен делать свои проверки и по-возможности разруливать "косяки".


Да, судя по всему так и есть.

JR>>А вот тот пример с дизассемблированием, правкой и повторной компиляцией с помощью ILasm — а что покажет ILDasm, если ему скормить результат работы ILAsm? Там сохранится внесённое вручную Employee::GetYearsEmployed, или опять оказывается исходная EmployeeBase::GetYearsEmployed?


MC>Ну, я же это написал в том свое посте:


Извиняюсь, вчера уже полусонный был, допустил ненимательность, а сегодня не посмотрел ещё раз.
"Нормальные герои всегда идут в обход!"
Re[17]: Базовый вопрос по наследованию
От: MozgC США http://nightcoder.livejournal.com
Дата: 06.02.11 12:37
Оценка:
Здравствуйте, vf, Вы писали:

vf>Покоя нет мне... как же так, выходит что здесь ошибка в описании?! Или я не правильно понял?

vf>

That is, the method is chosen based on the runtime type of obj rather than the compile-time class visible in the method pointer.


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

Хотя, по поводу того, что если в отдельной сборке переопределить метод у дочернего класса и подменить сборку, после чего все равно вызовется метод базового класса, — тут можно выдать это за фичу. Т.е. клиент, когда писал программу, ожидал что вызовется метод базового класса, он не рассчитывал что может появиться метод у дочернего класса, т.к. метод не виртуальный. А тут ему подменивают сборку и поведение. Но все работает как и ожидал клиент при компиляции. Т.е. можно посмотреть на это с этой стороны
Re[18]: Базовый вопрос по наследованию
От: vf  
Дата: 06.02.11 13:45
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Хотя, по поводу того, что если в отдельной сборке переопределить метод у дочернего класса и подменить сборку, после чего все равно вызовется метод базового класса, — тут можно выдать это за фичу. Т.е. клиент, когда писал программу, ожидал что вызовется метод базового класса, он не рассчитывал что может появиться метод у дочернего класса, т.к. метод не виртуальный. А тут ему подменивают сборку и поведение. Но все работает как и ожидал клиент при компиляции. Т.е. можно посмотреть на это с этой стороны


Да возможно...хотя и не однозначно. Как в описании callvirt мне кажется все таки логичнее. Интересно что:

1. если совсем убить метод в родителе, то получим MissingMethodException
2. а, если сделать метод в родителе абстрактным — тогда вызывается метод потомка

Это все без перекомпиляции самого приложения конечно.
Re[15]: Базовый вопрос по наследованию
От: Sinclair Россия https://github.com/evilguest/
Дата: 07.02.11 11:18
Оценка: 11 (2)
Здравствуйте, vf, Вы писали:

vf>Похоже что, все таки отработает как положено, лениво проверять

Нет. Читать здесь.
Или здесь.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.