.. но похоже, что компилятор делает «плохое предположение». Кто-нибудь может мне это объяснить?
При использовании dynamic
всего выражение обрабатываются во время компиляции, как динамического выражения, что вызывает компилятор для лечения все, как динамические и получить время выполнения связывания.
Это объясняется в 7.2 спецификации языка C#:
При отсутствии динамических выражений не участвует, C# по умолчанию для статического связывания, а это означает, что типы во время компиляции составных выражений используются в выборе обработать. Однако, когда одно из составных выражений в перечисленных выше операциях является динамическим выражением, операция вместо этого динамически связана.
Это в основном означает, что большинство операций (типы перечислены в разделе 7.2 спецификации), которые любой элемент, который объявлен как dynamic
будет оцениваться как dynamic
, и результат будет dynamic
.
В вашем случае, это утверждение:
var settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
использует динамический, поэтому он getst reated как динамическое выражение. Поскольку «вызов метода» является одной из операций C#, подлежащих привязке (7.2), лечит компилятор это как динамический Bound, что вызывает это оценить на:
dynamic settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
Это, в свою очередь, приводит к тому, DateTime.Parse
выражения должны быть динамичными грань, которая, в свою очередь, делает их возвращение dynamic
.
Ваш «фикс» работает, когда вы делаете DateTime startDate = DateTime.Parse(settings.startDate);
, потому что это заставляет неявное динамическое преобразование (описано в разделе 6.1.8 в спецификации) результата метода DateTime.Parse к DateTime:
Неявное динамическое преобразование существует из выражения типа dynamic для любого типа T. Преобразование динамически связано (§7.2.2), что означает, что неявное преобразование будет искать во время выполнения из типа времени выполнения выражения к T. Если преобразование не найдено, генерируется исключение во время выполнения.
В этом случае преобразование действительно, поэтому вы можете полностью переключить все на статическое привязку с этого момента.
«Кто-нибудь может объяснить это мне?» вероятно, должно быть: «Может ли Эрик Липперт объяснить это нам?» – dasblinkenlight
Это меня удивило. Я не поверил тебе, пока сам не пробовал! :-) – Simon
Другим способом решения этой проблемы является принудительный тип 'string' в аргументе *' DateTime.Parse() ', например:' var startDate = DateTime.Parse ((string) settings.startDate) ' – dasblinkenlight