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

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

问题描述

我正在使用以下代码将一些 Json 转换为动态对象.当我在动态类型的属性上使用 DateTime.Parse 时,我希望 var 猜测它的类型是 DateTime...相反,它保持动态.这不可能是对的,对吗?

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?

完整示例如下.

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 和 userId 仍然是动态的,这意味着我不能在以后的 Lambda 表达式中使用它们.显然,我可以通过以下方式修复代码:

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?

谢谢

推荐答案

..但似乎编译器正在做出错误的猜测".谁能给我解释一下?

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

当你使用dynamic时,整个表达式在编译时被当作一个动态表达式,这会导致编译器把所有的东西都当作动态的,并获得运行时绑定.

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.

这在 C# 语言规范的 7.2 中有解释:

This is explained in 7.2 of the C# Language specification:

当不涉及动态表达式时,C#默认为静态绑定,这意味着在选择过程中使用组成表达式的编译时类型.但是,当上面列出的操作中的组成表达式之一是动态表达式时,该操作将改为动态绑定.

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.

这基本上意味着大多数具有声明为 dynamic 的元素的操作(类型在规范的第 7.2 节中列出)将被评估为 dynamic,结果将是 dynamic.

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.

就您而言,此声明:

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

使用动态,因此,它被视为动态表达式.由于方法调用"是受绑定 (7.2) 约束的 C# 操作之一,因此编译器将其视为动态绑定,从而导致其计算为:

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);

反过来,这会导致 DateTime.Parse 表达式被动态绑定,从而使它们返回 dynamic.

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

当您执行 DateTime startDate = DateTime.Parse(settings.startDate); 时,您的修复"有效,因为这会强制隐式动态转换(在规范的第 6.1.8 节中描述)DateTime.Parse 方法到 DateTime 的结果:

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:

存在从 dynamic 类型的表达式到任何类型 T 的隐式动态转换.该转换是动态绑定的(第 7.2.2 节),这意味着将在运行时从运行时类型寻求隐式转换将表达式转换为 T.如果未找到转换,则抛出运行时异常.

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# 是否为 var 选择了错误的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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