В C # все привязано заранее, если вы не используете интерфейс Reflection.
Ранняя привязка просто означает, что целевой метод найден во время компиляции и создается код, который его вызовет. Независимо от того, виртуальный он или нет (это означает, что есть дополнительный шаг, чтобы найти его во время вызова, не имеет значения). Если метод не существует, компилятор не сможет скомпилировать код.
Поздняя привязка означает, что целевой метод просматривается во время выполнения. Часто для его поиска используется текстовое имя метода. Если метода нет, бац. Программа выйдет из строя или перейдет в некоторую схему обработки исключений во время выполнения.
Большинство языков сценариев используют позднее связывание, а скомпилированные языки используют раннее связывание.
C # (до версии 4) не связывает поздно; Однако они могут использовать для этого API отражения. Этот API компилируется в код, который ищет имена функций, копаясь в сборках во время выполнения. VB может выполнить позднее связывание, если параметр Option Strict отключен.
Связывание обычно влияет на производительность. Поскольку для позднего связывания требуется поиск во время выполнения, это обычно означает, что вызовы методов выполняются медленнее, чем вызовы методов раннего связывания.
Для нормальной функции компилятор может определить ее числовое расположение в памяти. Затем, когда функция вызывается, она может сгенерировать инструкцию для вызова функции по этому адресу.
Для объекта, у которого есть какие-либо виртуальные методы, компилятор сгенерирует v-таблицу. По сути, это массив, содержащий адреса виртуальных методов. Каждый объект, имеющий виртуальный метод, будет содержать скрытый член, сгенерированный компилятором, который является адресом v-таблицы. Когда вызывается виртуальная функция, компилятор определяет позицию соответствующего метода в v-таблице. Затем он сгенерирует код для просмотра v-таблицы объектов и вызова виртуального метода в этой позиции.
Итак, для виртуальной функции выполняется поиск. Это сильно оптимизировано, поэтому во время выполнения это произойдет очень быстро.
Ранняя граница
- Компилятор может определить, где будет находиться вызываемая функция во время компиляции.
- Компилятор может гарантировать на раннем этапе (до запуска кода любой из программ), что функция будет существовать и быть вызываемой во время выполнения.
- Компилятор гарантирует, что функция принимает правильное количество аргументов и что они имеют правильный тип. Он также проверяет, что возвращаемое значение имеет правильный тип.
Поздняя привязка
- Поиск займет больше времени, потому что это не простой расчет смещения, обычно требуется сравнение текста.
- Целевая функция может не существовать.
- Целевая функция может не принимать переданные ей аргументы и может иметь возвращаемое значение неправильного типа.
- В некоторых реализациях целевой метод может фактически изменяться во время выполнения. Таким образом, поиск может выполнять другую функцию. Я думаю, что это происходит на языке Ruby, вы можете определить новый метод для объекта во время работы программы. Позднее связывание позволяет вызовам функций начинать вызывать новое переопределение для метода вместо вызова существующего базового метода.