[英]If statement evaluates to false but still branches as if it was true
我很难过。 在异步方法中,我有一些初始保护语句,如果满足特定条件则抛出异常。
其中之一是以下内容:
var txPagesCount = _transactionPages.Count;
if (txPagesCount == 0)
throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId));
这应该确保_transactionPages
字典中有页面,如果没有则抛出。
这是我运行时发生的事情(发布和调试版本,附加调试器):
所以字典中的页数是3。
因此,正如预期的那样,将3比0的if语句评估为false。
但是,当进一步迈进时:
它进入分支,好像if语句计算为true,并抛出异常。
我在这里错过了什么?
UPDATE
当我这样做:
private static readonly object _globalLock = new object();
public async Task<Checkpoint> CommitAsync(PageNumber dataRoot, PageNumber firstUnusedPage)
{
lock (_globalLock)
{
if (IsCompleted)
throw new InvalidOperationException(string.Format("Cannot commit completed transaction {0}", _txId));
var txPagesCount = _transactionPages.Count;
if (txPagesCount == 0)
throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId));
}
if语句不分支以抛出异常。 调试和发布版本都是这种情况。 是什么搞砸了调用堆栈? 另外,如果不是锁,我添加System.Threading.Thread.MemoryBarrier();
在if
语句之后,它不会进入分支。
更新2
这个谜团变得更大了。 这几乎就像使用了c ++范围规则:D下面的代码( 在调试版本中 )将显示预期的行为:不进入分支而不抛出。 在发布版本中 ,它将进入分支并像以前一样抛出。
private static readonly object _globalLock = new object();
public async Task<Checkpoint> CommitAsync(PageNumber dataRoot, PageNumber firstUnusedPage)
{
//lock (_globalLock)
{
if (IsCompleted)
throw new InvalidOperationException(string.Format("Cannot commit completed transaction {0}", _txId));
var txPagesCount = _transactionPages.Count;
if (txPagesCount == 0)
throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId));
}
如果我注释掉“范围括号”,它将进入分支并抛出异常(如我原始图像中所示)。
最后? UPDATE
那很糟糕。 我对不相关的代码区域做了一些更改,现在我不再能够重现问题了。
哇,异步调试。
我只有一种方法可以有效地做到这一点。 使用跟踪(希望是正确的东西,也许是log4net)。 确保在每一行输出时间戳和threadId。 (还支持在需要时每次调用跟踪库的输出同步,而不必一直打开)
真的是这样的。
注意:只需写入文件或标准输出就可以获得第一个红色,但如果您开始使用它,请获取一个库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.