В следующем коде есть статический метод Foo()
, вызывающий метод экземпляра Bar()
:
public sealed class Example
{
int count;
public static void Foo( dynamic x )
{
Bar(x);
}
void Bar( dynamic x )
{
count++;
}
}
Он компилируется без ошибок *, но генерирует исключение связывания во время выполнения. Удаление динамического параметра для этих методов вызывает ошибку компилятора, как и ожидалось.
Итак, почему наличие динамического параметра позволяет компилировать код? ReSharper также не показывает это как ошибку.
Изменить 1: * в Visual Studio 2008
Изменить 2: добавлено, sealed
так как возможно, что подкласс может содержать статический Bar(...)
метод. Даже запечатанная версия компилируется, когда во время выполнения невозможно вызвать какой-либо другой метод, кроме метода экземпляра.
c#
visual-studio-2008
dynamic
compiler-errors
Майк Скотт
источник
источник
dynamic
если в этом нет необходимости.Ответы:
ОБНОВЛЕНИЕ: ответ ниже был написан в 2012 году, до введения C # 7.3 (май 2018 года) . В разделе « Что нового в C # 7.3» , в разделе « Улучшенные кандидаты на перегрузку» , пункт 1, объясняется, как изменились правила разрешения перегрузки, чтобы нестатические перегрузки отбрасывались раньше. Итак, ответ ниже (и весь этот вопрос) на данный момент в основном представляет только исторический интерес!
(До C # 7.3 :)
По какой-то причине разрешение перегрузки всегда находит лучшее совпадение перед проверкой статического и нестатического. Пожалуйста, попробуйте этот код со всеми статическими типами:
Это не будет компилироваться, потому что лучшая перегрузка - это перегрузка
string
. Но послушайте, это метод экземпляра, поэтому компилятор жалуется (вместо того, чтобы использовать вторую по величине перегрузку).Дополнение: Итак, я думаю, что объяснение
dynamic
примера исходного вопроса заключается в том, что для обеспечения единообразия, когда типы являются динамическими, мы также сначала находим лучшую перегрузку (проверяя только номер параметра и типы параметров и т.д., а не статические и не статические). -статический), и только потом проверять статичность. Но это означает, что статическая проверка должна дождаться времени выполнения. Отсюда наблюдаемое поведение.Позднее добавление: некоторую предысторию того, почему они выбрали этот забавный порядок, можно вывести из этого сообщения в блоге Эрика Липперта .
источник
dynamic
был представлен в языке, я думаю, что разработчики C # сказали: «Мы не будем рассматривать (2) время компиляции, когда этоdynamic
выражение». Итак, моя цель здесь - придумать, почему они решили не проверять статичность по сравнению с экземпляром до времени выполнения. Я бы сказал, эта проверка происходит во время привязки .У Foo есть параметр «x», который является динамическим, что означает, что Bar (x) является динамическим выражением.
В примере было бы вполне возможно иметь такие методы, как:
В этом случае правильный метод будет разрешен, поэтому утверждение Bar (x) совершенно верно. Тот факт, что существует метод экземпляра Bar (x), не имеет значения и даже не рассматривается: по определению , поскольку Bar (x) является динамическим выражением, мы отложили разрешение до времени выполнения.
источник
«Динамическое» выражение будет привязано во время выполнения, поэтому, если вы определяете статический метод с правильной сигнатурой или методом экземпляра, компилятор не будет его проверять.
«Правильный» метод будет определен во время выполнения. Компилятор не может знать, есть ли там допустимый метод во время выполнения.
Ключевое слово «dynamic» определено для динамических языков и языков сценариев, где метод может быть определен в любое время, даже во время выполнения. Сумасшедшие вещи
Здесь образец, который обрабатывает целые числа, но не строки, потому что метод находится в экземпляре.
Вы можете добавить метод для обработки всех "неправильных" вызовов, которые невозможно обработать.
источник