繁体   English   中英

如果语句的计算结果为false,但仍然分支,就好像它是真的一样

[英]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。

if语句的计算结果为false

因此,正如预期的那样,将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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM