我刚刚在 VS2015 .Net v4.5.2 控制台应用程序中输入了以下代码:
dynamic fromString = "blah", toString = "blah2";
DateTime fromDate, toDate;
if (DateTime.TryParse(fromString.ToString(), out fromDate) && DateTime.TryParse(toString.ToString(), out toDate)) {
Console.WriteLine(fromDate);
Console.WriteLine(toDate);
}
Run Code Online (Sandbox Code Playgroud)
出乎意料的是,我收到错误“使用未分配的局部变量 toDate”。我没想到,因为只有在从第二个 TryParse 中为“toDate”分配了一个值时,才会输入 if 语句。
不用说,它可以通过为 'toDate' 分配一个值来解决:
DateTime fromDate, toDate = DateTime.MinValue;
Run Code Online (Sandbox Code Playgroud)
或者将 && 更改为 & 以便无论第一次失败如何都会执行两个 TryParses。
但是,我想知道为什么会发生错误?如果变量 fromString 和 toString 是字符串,则不会发生错误并且编译器不会给出 toDate 未分配的错误。因此我想知道为什么编译器对待string和dynamic.ToString()不同?
这是因为您使用了短路运算符 &&,这意味着如果第一个 TryParse 返回 false,则永远不会执行第二个 TryParse,从而使 ToDate 变量未分配。
试试看,用 & 替换 && ,您的错误将消失,因为现在将始终执行两个 TryParse 调用。
编译器不够聪明(它不分析您的逻辑)知道在某些情况下不会执行内部代码。
编辑:@Simon,我重新阅读了您的问题,发现您已经知道这一点...也许是因为 .ToString 始终存在于对象上,但并不总是存在于动态上(例如,当它是 com 对象时),并且在那种情况下,编译器会做更少的检查?
这是 Roslyn 的一个重大变化,记录如下:
以前的编译器为动态表达式实现的明确赋值规则允许某些代码情况可能导致读取未明确赋值的变量。有关这方面的一份报告,请参阅https://github.com/dotnet/roslyn/issues/4509。
[剪辑说明性示例]
由于这种可能性,如果 val 没有初始值,编译器不得允许编译该程序。即使 val 没有初始值,以前版本的编译器(VS2015 之前)也允许该程序编译。Roslyn 现在诊断出读取可能未初始化变量的尝试。