Mar*_*ers 13 c# var dynamic c#-4.0
我使用以下代码将一些Json转换为动态对象.当我在动态类型的属性上使用DateTime.Parse时,我希望var猜测它的类型是DateTime ......相反,它保持动态.这不可能是对的,可以吗?
完整的例子如下.
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);
Run Code Online (Sandbox Code Playgroud)
startDate,endDate和userId都是动态的,这意味着我不能在以后的Lambda表达式中使用它们.显然,我可以用以下代码修复代码:
DateTime startDate = DateTime.Parse(settings.startDate);
DateTime endDate = DateTime.Parse(settings.endDate);
int userId = int.Parse(settings.userId);
Run Code Online (Sandbox Code Playgroud)
..但似乎编译器正在做出"糟糕的猜测".任何人都可以向我解释这个吗?
谢谢
Ree*_*sey 13
..但似乎编译器正在做出"糟糕的猜测".任何人都可以向我解释这个吗?
使用时dynamic,整个表达式在编译时被视为动态表达式,这会导致编译器将所有内容视为动态并获取运行时绑定.
这在C#语言规范的7.2中有解释:
当不涉及动态表达式时,C#默认为静态绑定,这意味着在选择过程中使用组成表达式的编译时类型.但是,当上面列出的操作中的一个组成表达式是动态表达式时,操作将被动态绑定.
这基本上意味着大多数操作(类型在规范的7.2节中列出)具有任何被声明为的元素dynamic将被评估为dynamic,结果将是a dynamic.
在您的情况下,此声明:
var settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
Run Code Online (Sandbox Code Playgroud)
使用动态,因此,它被视为动态表达式.由于"方法调用"是受绑定(7.2)的C#操作之一,因此编译器将其视为动态绑定,这会使其评估为:
dynamic settings = new JavaScriptSerializer().Deserialize<dynamic>(json);
Run Code Online (Sandbox Code Playgroud)
反过来,这会使DateTime.Parse表达式成为动态绑定,从而使它们返回dynamic.
当你这样做时,你的"修复"会起作用,DateTime startDate = DateTime.Parse(settings.startDate);因为这会强制将DateTime.Parse方法的结果隐式动态转换(在规范的第6.1.8节中描述)到DateTime:
从dynamic类型的表达式到任何类型T都存在隐式动态转换.转换是动态绑定的(第7.2.2节),这意味着将在运行时从表达式的运行时类型中搜索隐式转换如果没有找到转换,则抛出运行时异常.
在这种情况下,转换是有效的,因此您可以有效地将所有内容切换回静态绑定.