将Nullable属性默认值设置为Nothing不能按预期工作

时间:2012-07-12 05:08:35

标签: vb.net nullable short-circuiting

我有一个Nullable Integer类型的属性,默认值为Nothing,如下所示:

Property TestId As Integer? = Nothing

以下代码将属性TestId评估为Nothing(如所需)

Dim test As RadTreeNode = rtvDefinitionCreate.FindNodeByValue(DefinitionHeaderEnum.Test)
If test Is Nothing Then
    definition.TestId = Nothing
Else
    definition.TestId = test.Nodes(0).Value
End If

但下面的代码评估为0(Integer的默认值,即使Integer?的默认值为Nothing

Dim test As RadTreeNode = rtvDefinitionCreate.FindNodeByValue(DefinitionHeaderEnum.Test)
definition.TestId = If(IsNothing(test), Nothing, test.Nodes(0).Value)

上述代码有什么问题?任何帮助??

(稍后在代码中调用属性时,属性为0)

1 个答案:

答案 0 :(得分:2)

这是因为您正在使用Option Strict Off编译代码。

如果您使用Option Strict On编译代码,编译器会给您一个错误,告诉您它无法从String转换为Integer?,避免在运行时出现这种情况


在VB.NET中使用properties / ternary operator / option strict off时,这很奇怪。

请考虑以下代码:

Class Test
    Property NullableProperty As Integer? = Nothing
    Public NullableField As Integer? = Nothing
End Class

Sub Main()
    ' Setting the Property directly will lest the ternary operator evaluate to zero
    Dim b = New Test() With {.NullableProperty = If(True, Nothing, "123")}
    b.NullableProperty = If(True, Nothing, "123")

    ' Setting the Property with reflection or setting a local variable 
    ' or a public field lets the ternary operator evaluate to Nothing
    Dim localNullable As Integer? = If(True, Nothing, "123")
    Dim implicitLocal = If(True, Nothing, "123")
    b.NullableField = If(True, Nothing, "123")
    b.GetType().GetMethod("set_NullableProperty").Invoke(b, New Object() {If(True, Nothing, "123")})
    b.GetType().GetProperty("NullableProperty").SetValue(b, If(True, Nothing, "123"), Nothing)
End Sub

要考虑的另一个区别:

Dim localNullable As Integer? = If(True, Nothing, "123") 

将评估为Nothing,但

Dim localNullable As Integer? = If(SomeNonConstantCondition, Nothing, "123") 

将评估为0


您可以创建一个扩展方法来为您执行令人讨厌的工作。

<Extension()>
Function TakeAs(Of T, R)(obj As T, selector As Func(Of T, R)) As R
    If obj Is Nothing Then
        Return Nothing
    End If
    Return selector(obj)
End Function

并将其称为

definition.TestId = test.TakeAs(Of Int32?)(Function(o) o.Nodes(0).Value)