I am using the following code to convert some Json into a dynamic object. When I use DateTime.Parse on a property of my dynamic type I would expect the var to guess that it’s type is a DateTime… instead, it stays as a dynamic. This can’t be right, can it?
Full example below.
var settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
var startDate = DateTime.Parse(settings.startDate);
var endDate = DateTime.Parse(settings.endDate);
var userId = int.Parse(settings.userId);
startDate, endDate and userId are all still dynamic, which means I then cannot use them in a later Lambda expressions. Obviously, I can fix the code with:
DateTime startDate = DateTime.Parse(settings.startDate);
DateTime endDate = DateTime.Parse(settings.endDate);
int userId = int.Parse(settings.userId);
..but it seems like the compiler is making a ‘bad guess’. Can anyone explain this to me?
Thanks
When you use
dynamic, the entire expression is treated at compile time as a dynamic expression, which causes the compiler to treat everything as dynamic and get run-time binding.This is explained in 7.2 of the C# Language specification:
This basically means that most operations (the types are listed in section 7.2 of the spec) which have any element that is declared as
dynamicwill be evaluated asdynamic, and the result will be adynamic.In your case, this statement:
Uses dynamic, so, it getst reated as a dynamic expression. Since “Method invocation” is one of the C# operations subject to binding (7.2), the compiler treats this as dynamic bound, which causes this to evaluate to:
This, in turn, causes the
DateTime.Parseexpressions to be dynamic bound, which in turn makes them returndynamic.Your “fix” works when you do
DateTime startDate = DateTime.Parse(settings.startDate);because this forces an implicit dynamic conversion (described in section 6.1.8 of the spec) of the result of the DateTime.Parse method to a DateTime:In this case, the conversion is valid, so you effectively switch everything back to static binding from then on.