昨晚工作到很晚,我们试图找出原因失败的原因。验证检查失败时应该没有。
我们最终在这段代码中添加了一个print语句(从Reflector中反汇编,以便检查代码实际上是我们编写的代码):
public static string Redacted(string name, DateTime lastModified)
{
long ticks = lastModified.Ticks;
if ((ticks != (ticks - (ticks % 10000L))) &&
(lastModified != DateTime.MaxValue))
{
Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
ticks, ticks - (ticks % 10000L)));
打印(重新格式化):
Last Modified Date = '22/03/2011 12:16:22.000'.
Ticks = '634363497820000000'.
TicksCalc = '634363497820000000'
但条件是“ticks
”(等于上面打印的Ticks)不等于“(ticks - (ticks % 10000))
”(等于TicksCalc)! 634363497820000000!= 634363497820000000?!
为了确定这里发生了什么,我们又添加了两个陈述:
long ticks = lastModified.Ticks;
/* Added following two lines: */
long num2 = ticks - (ticks % 10000L);
Log.Debug((ticks == num2).ToString());
/* */
if ((ticks != (ticks - (ticks % 10000L))) &&
(lastModified != DateTime.MaxValue))
{
Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
ticks, ticks - (ticks % 10000L)));
应该有,这个打印true
(当测试时使用相同的值),并且没有写第二行。
感觉有点迷失,我们再次删除了两行,重新编译,然后重新编译。原来的行为重演了。
今天早上I recorded a video。
首先,视频显示使用“损坏”代码在方法中命中断点,然后使用“工作”代码重建和重新运行。请注意,即使调试器显示if
条件评估为false
,仍然会输入正文。
我已经看到这样的事情发生在调试器观察之前,因为调试器强制要求评估一些事情,但无论是否使用调试器都会发生这种情况。
此外,这仅在发布模式下发生(即启用了JIT优化)。
以下是两个版本的反汇编方法:working,not working。我不能真正阅读汇编,所以我将它们发布在这里是为了澄清。
我希望答案不是我完全忽略的明显的答案......!
编辑:这是IL。我认为它没有任何问题,因为它反编译为正确的C#:
更新:
Confirmed as a bug by Microsoft, to be fixed in the next release
答案 0 :(得分:9)
我用简化的代码进行了一些实验: http://nopaste.info/2c99a0e028_nl.html
最有趣的变化是:
static readonly long variableZero=0;
const long constZero=0;
public static void Broken2( long ticks2)
{
long ticks = ticks2+variableZero;
if (ticks != (ticks - (ticks % 10000L)))
{
string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
"n/A",
ticks, ticks - (ticks % 10000L)).Dump();
}
}
如果我将variableZero
替换为constantZero
则可行。
所以我很确定它是一个抖动或编译器错误。
我在MS Connect上提交了一个bug报告: https://connect.microsoft.com/VisualStudio/feedback/details/671105/jitter-or-c-compiler-bug#details
更新:只有在未附加调试程序时才会出现奇怪的行为。即,当启用Jit优化时。所以我很确定这是一个抖动错误。
对于没有linq-pad的人来说,现在有一个简单的C#控制台项目:http://nopaste.info/00a0e37328_nl.html
答案 1 :(得分:1)
查看此主题。
If statement weirdness in Visual Studio 2008
归结为此,你无法一直信任调试器。
要“修复”if语句,请向其添加空的 else {} 语句。调试器将按预期工作。
答案 2 :(得分:1)
这确实看起来像是 - 哼哼 - jitterbug。你可以在“if”语句中设置一个断点,并在它击中之后向我们展示反汇编视图的截图吗?
答案 3 :(得分:1)
我刚才有类似的东西。 在我的情况下,它与我正在比较2个整数值的事实有关,其中一个值实际上是对盒装整数的引用而另一个值是真正的原始值。
问题在于,如果打印出盒装整数和基元的值,它们看起来是一样的,但比较它们是另一回事。您将获得参考比较而不是值比较。
答案很简单:
long ticks = lastModified.Ticks;
long num2 = ticks - (ticks % 10000L);
if ((ticks != num2) && (lastModified != DateTime.MaxValue))
{ do your thing here! }
答案 4 :(得分:0)
那太疯狂了。您是否尝试过无缘无故地重新排序if语句?
if (lastModified != DateTime.MaxValue && ticks != (ticks - (ticks % 10000L))
此外,如果这不起作用(因为它不应该,因为它首先应该不是问题),你能否以问题的形式显示代码的实际IL?
另外一件事,ticks
检查无法简化为:
(ticks % 10000L) != 0