VB具有空值的单行

时间:2014-10-10 15:36:32

标签: asp.net vb.net if-statement nullable

我有以下代码,我认为它不能正常运行,我无法弄清楚原因。

dim total as decimal? = If(first Is Nothing OrElse second Is Nothing, _
                           Nothing, _
                           Math.Abs(If(first, 0D)) - Math.Abs(If(second, 0D)))

如果 first second 都不是,那么就不需要在total中放置任何内容。但是,如果它们都有值,则需要将它们更改为正值,并且需要计算first - second。第一个和第二个都是可以为空的小数(十进制?)。

预期结果:

first = nothing
second = nothing
total = nothing

实际结果:

first = nothing
second = nothing
total = 0D

我无法理解为什么if语句没有跳转到真正的段并将Nothing放入变量total

2 个答案:

答案 0 :(得分:2)

If()运算符是强类型的,但编译器必须根据输入推断结果的类型。

在这种情况下,它无法从第一个选项(Nothing)推断出类型,因为Nothing本身没有类型,并且与C#的null不同,Nothing可以减少为值类型(这一点很重要)。因此编译器必须查看第二个选项:Math.Abs(If(first, 0D)) - Math.Abs(If(second, 0D))。此表达式的类型评估为Decimal ... a Decimal?。因此,整个If()表达式的结果类型为Decimal,而不是Decimal?。您将结果分配给Decimal?并不重要。

  

我无法理解为什么if语句没有跳转到真正的段并将Nothing放入变量total

这正是它正在做的事情。但是,如前所述,VB.Net中的Nothing可以分配给值类型。在赋值之前,Nothing转换为Decimal,因为这是If()表达式的结果类型。如果是十进制,则指定Nothing的值会导致默认的十进制值0D ...因此您的结果。

我没有对此进行过测试,但我认为您可以通过在If()运算符中明确地将False表达式强加为Decimal? / Nullable(Of Decimal)来解决此问题,以获得所需的结果。这将告诉编译器为Decimal?表达式的类型推断Decimal而不是If(),因此从该表达式返回Nothing将具有所需的输出。

答案 1 :(得分:0)

我已经恢复编译扩展,允许绝对值函数在可空的十进制上执行,如果它是Nothing或非负,则返回值,否则乘以-1并返回。这样,如果它什么都不返回,那么计算结果就像预期的一样。

dim total as decimal? = first.ToAbsoluteValue() - second.ToAbsoluteValue()

<System.Runtime.CompilerServices.Extension()> Friend Function ToAbsoluteValue(value As Decimal?) As Decimal? If value Is Nothing OrElse value >= 0 Then Return value Return Math.Abs(If(value, 0D)) End Function

如果有人知道如何将这个添加到Math.Abs​​()重载,这将是一个更清洁的选项。