理解空值合并运算符(??)

9

我有一个自定义的WebControl,它实现了一个.Value获取器/设置器,返回一个可空的<decimal>。

这是一个客户端过滤的文本框(一个TextBox的子类,包含JavaScript和一些服务器端逻辑来设置/获取值)。

下面是这个控件的getter和setter:

public decimal? Value
{
    get
    {
        decimal amount = 0;
        if (!decimal.TryParse(this.Text, NumberStyles.Currency, null, out amount))
        {
            return null;
        }
        else
        {
            return amount;
        }
    }
    set
    {
        if (!value.HasValue)
        {
            this.Text = "";
        }
        else
        {
            this.Text = string.Format("${0:#,##0.00}", value);
        }
    }
}

我看到的问题是,这个语句的输出是:
decimal Amount = uxAmount.Value ?? 0M;

uxAmount.Value返回10000时,我看到金额被设置为“0”。

这符合我的预期(请原谅大小写的更改):

decimal? _Amount = uxAmount.Value;
decimal amount = _Amount ?? 0;

最近我在调用一个定义在Linq2Sql数据上下文中的UDF函数时,遇到了这种行为,同时还使用了null合并运算符。也就是说,我知道我的UDF调用返回了预期的值,但我却得到了RHS值。

更令我困惑的是,如果我在观察窗口中评估uxAmount.Value,我会得到类型为Nullable<decimal>的10000。

以下是我尝试过的一些表达式:

decimal? _Amount = uxAmount.Value; //10000
decimal amount = _Amount ?? 0; //10000
decimal amount2 = _Amount ?? 0M; //10000
decimal Amount = uxAmount.Value ?? 0M; //0

然后,我在上述4个表达式后添加了这个表达式。
decimal amount3 = (uxTaxAmount.Value) ?? 0M;

现在
decimal Amount = uxAmount.Value ?? 0M; //10000
decimal amount3 = (uxAmount.Value) ?? 0M; //0

似乎最后一个调用总是0,但根据上面的getter/setter使用TryParse解析出来的uxAmount.Value(从.Text中解析出来)的值是稳定的。我在断点处停止了,没有其他线程可以操作这个值。
请注意使用M后缀将常量强制为十进制,因为它是整数,我怀疑存在类型转换问题。
有什么想法吗?
左右两边的值似乎都是稳定的且已知。
--编辑--从VS2010中获取一些屏幕截图
查看下面关于变量状态的对话框以及更多详细信息

1
这是一个可空的十进制数[decimal?] - 请参见问题顶部的getter/setter定义。 - agrath
1
你确定调试器对你显示的是正确的吗?你尝试向下跨越几行来确保你有更新后的 amount3 值了吗?因为当 XXX 是可空十进制数时,XXX ?? 0M 将是一个(非可空)十进制数,如果 XXX 不为空,则其值将为 XXX,否则为零。 - Jeppe Stig Nielsen
悬停在uxAmount.Value上会显示10000,表达式的结果似乎始终为0,除非我在下面进一步重新评估它,我将在下面发布几张屏幕截图。 - agrath
好奇,你的C#和.NET版本是什么?操作系统位数是多少? - Vlad
2
我相信这只是调试器的问题。有时候你需要再往前走一步。也许翻译后的代码(IL)有一些优化,会让调试器感到困惑(或者说我不知道)。但我相信没有调试器的情况下,值将会在你期望的时间被更新。 - Jeppe Stig Nielsen
显示剩余8条评论
2个回答

1

结果是一个调试器问题。我非常担心我的??的使用有很多未知的副作用,我必须检查所有的项目并确保我改变了语法。 - agrath
此外,.Value 是十进制数吗?(Nullable<decimal>) - agrath
哦,我没有想到这一点,因为它是可空的十进制数,实际值应该是Value.Value :) - Michael Christensen

1

(此答案是根据我上面的评论构建的。)

您确定调试器对您显示了正确的内容吗?您尝试向下跨越几行以确保您具有amount3的更新值了吗?

我确定这只是调试器的问题。有时您需要再往前走一点。也许翻译后的代码(IL)有一些优化,会使调试器感到困惑(或者我知道什么)。但是没有调试器,该值将在您期望的时间更新。

我见过其他经验丰富的开发人员被类似情况搞糊涂,所以我知道调试器有时候会“落后于一行代码”,当看到对本地变量的分配时。也许有人可以找到一个讨论这个问题的链接?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接