Я подозреваю, что вы обнаружите, что он использует call
вместо callvirt
, если вы посмотрите на IL.Компилятор C # всегда использует callvirt
, даже для не виртуальных методов, потому что он вызывает проверку недействительности.
Это ошибка?Ну, не обязательно.Это зависит от того, что в спецификации языка F # говорится о вызовах методов для нулевых ссылок.Вполне возможно, что в нем говорится, что метод будет вызываться (не виртуально) с нулевой ссылкой «this», что именно и произошло.
C # указывает, что такого рода разыменование вызоветNullReferenceException
, но это выбор языка.
Я подозреваю, что подход F # может быть немного быстрее из-за недостатка проверки на нулевое значение ... и не забывайте, что нулевые ссылки менее ожидаемы"в F #, чем в C # ... что может объяснить другой подход, принятый здесь.Или, конечно, это может быть просто недосмотр.
РЕДАКТИРОВАТЬ: я не специалист по чтению спецификации F #, но по крайней мере в разделе 6.9.6 предлагает мне , что этоошибка:
6.9.6 Оценка применения методов
Для сложных применений методов разработанной формой выражения будет либо expr.M (args), либо M (args).
(необязательные) выражения и аргументы вычисляются в порядке слева направо, а тело члена оценивается в среде с формальными параметрами, которые сопоставляются с соответствующими значениями аргументов.
Если значение expr равно нулю, то возникает исключение NullReferenceException.
Если метод представляет собой виртуальный интервал отправки (то есть метод, которыйобъявляется абстрактным), тогда тело члена выбирается в соответствии с картами отправки значения expr.
Независимо от того, считается ли это разработанным приложением или нет, это немного за граньюя, ябред ... но я надеюсь, что это было по крайней мере несколько полезно.