我有以下代码,我认为它不能正常运行,我无法弄清楚原因。
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
答案 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()重载,这将是一个更清洁的选项。