.. но кажется, что компилятор делает "неправильное предположение". Кто-нибудь может мне это объяснить?
Когда вы используете dynamic
, все выражение обрабатывается во время компиляции как динамическое выражение , что заставляет компилятор обрабатывать все как динамическое и получать привязку во время выполнения.
Это объясняется в 7.2 спецификации языка C #:
Когда динамические выражения не задействованы, в C # по умолчанию используется статическое связывание, что означает, что типы составных выражений во время компиляции используются в процессе выбора. Однако, когда одно из составных выражений в операциях, перечисленных выше, является динамическим выражением, операция вместо этого динамически связана.
Это в основном означает, что большинство операций (типы перечислены в разделе 7.2 спецификации), которые имеют любой элемент, объявленный как dynamic
, будут оцениваться как dynamic
, а результатом будет dynamic
.
В вашем случае это утверждение:
var settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
Используется динамическое, поэтому оно рассматривается как динамическое выражение. Поскольку «вызов метода» является одной из операций C #, подлежащих привязке (7.2), компилятор обрабатывает это как динамическую границу, что приводит к следующему значению:
dynamic settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
Это, в свою очередь, приводит к тому, что выражения DateTime.Parse
становятся динамически связанными, что, в свою очередь, заставляет их возвращать dynamic
.
Ваше «исправление» работает, когда вы делаете DateTime startDate = DateTime.Parse(settings.startDate);
, потому что это вызывает неявное динамическое преобразование (описанное в разделе 6.1.8 спецификации) результата метода DateTime.Parse в DateTime:
Существует неявное динамическое преобразование из выражения динамического типа в любой тип T. Преобразование является динамически связанным (§7.2.2), что означает, что неявное преобразование будет выполняться во время выполнения из типа времени выполнения выражения в T. Если преобразование не найдено, генерируется исключение времени выполнения.
В этом случае преобразование допустимо, поэтому с этого момента вы фактически переключаете все обратно на статическое связывание.