请问C#解析动态对象时,选择了错误的类型变种? [英] Does C# pick the wrong type for var when parsing a dynamic object?

查看:68
本文介绍了请问C#解析动态对象时,选择了错误的类型变种?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用下面的代码部分的Json转换成动态对象。当我使用DateTime.Parse我的动态类型的属性我期望VAR猜测,它的类型是一个DateTime ......相反,它保持为动态。这不可能是正确的,可以吗?



下面完整的示例。

  VAR设置=新的JavaScriptSerializer()反序列化<动态>(JSON); 

变种的startDate = DateTime.Parse(settings.startDate);
VAR结束日期= DateTime.Parse(settings.endDate);
VAR用户id = int.Parse(settings.userId);

的startDate,结束日期和用户id都仍然是动态的,这意味着我再不能在以后的LAMBDA使用它们表达式。很显然,我可以修复的代码:

 日期时间的startDate = DateTime.Parse(settings.startDate); 
DateTime的结束日期= DateTime.Parse(settings.endDate);
INT用户id = int.Parse(settings.userId);

..但似乎编译器做一个坏的猜测。谁能解释这样对我?



感谢


解决方案

..但似乎编译器做一个坏的猜测。谁能解释这样对我?




当您使用动态,整个表达式是在编译时视为的动态表情的,这会导致编译器把一切动态和获得运行时绑定。



这在C#语言规范7.2说明:




在没有动态表情都参与其中,C#默认为静态绑定,这意味着编译 - 时间类型的要素表达式的是在选择过程中使用。然而,在上面列出的操作的构成表达式的当一个是一个动态的表达,则操作代替动态绑定




这基本上意味着大多数操作(类型在规范的7.2节所列),它有一个声明为动态将被评估为动态任何元素,结果将是一个动态



在你的情况,这种说法:

  VAR设置=新。的JavaScriptSerializer()反序列化<动态>(JSON); 



使用动态,因此,它getst reated作为一个动态的表情。由于方法调用是C#操作主题之一结合(7.2),编译器将这种动态绑定,这将导致该评价为:

 动态设置=新的JavaScriptSerializer()反序列化<动态>(JSON); 

这反过来又导致 DateTime.Parse 表达式是动态绑定的,这反过来又使他们返回动态



您的作品修复的时候您日期时间的startDate = DateTime.Parse(settings.startDate); ,因为这种力量的结果的隐式动态转换(在规范第6.1.8所述) DateTime.Parse方法为DateTime:




这是隐式动态转换从任何类型T类型的动态的表达存在转换为动态绑定(§7.2.2),这意味着一个隐式转换将在从表达到T的运行时类型运行时征求如果没有找到转换,运行时异常。




在这种情况下,转换是有效的,所以你有效地切换一切回到静态从此约束力。


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

解决方案

..but it seems like the compiler is making a 'bad guess'. Can anyone explain this to me?

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:

When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of constituent expressions are used in the selection process. However, when one of the constituent expressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.

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 dynamic will be evaluated as dynamic, and the result will be a dynamic.

In your case, this statement:

var settings = new JavaScriptSerializer().Deserialize<dynamic>(json);

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:

dynamic settings = new JavaScriptSerializer().Deserialize<dynamic>(json);

This, in turn, causes the DateTime.Parse expressions to be dynamic bound, which in turn makes them return dynamic.

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:

An implicit dynamic conversion exists from an expression of type dynamic to any type T. The conversion is dynamically bound (§7.2.2), which means that an implicit conversion will be sought at run-time from the run-time type of the expression to T. If no conversion is found, a run-time exception is thrown.

In this case, the conversion is valid, so you effectively switch everything back to static binding from then on.

这篇关于请问C#解析动态对象时,选择了错误的类型变种?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆