【问题标题】:Set Nullable property default value to Nothing not working as desired将 Nullable 属性默认值设置为 Nothing 无法正常工作
【发布时间】:2012-07-12 05:08:34
【问题描述】:

我有一个属性,其类型为NullableInteger 默认值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)

【问题讨论】:

    标签: vb.net nullable short-circuiting


    【解决方案1】:

    这是因为您正在使用 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)
    

    【讨论】:

    • 我认为 Option Strict On 在这里没有帮助,因为 If 运算符会自动扩大从 Nothing 到 0 的转换(test.Nodes(0).Value 的类型) - 但解决方案应该有效!
    • @PaulB。 Option Strict On 会在此处帮助导致编译错误,突出问题。
    • 对我来说 Dim i As Integer? = If(True, Nothing, 1) 不会导致编译错误,而是将 Nothing 转换为 0,然后将 0 转换为可为空的 0。
    • @PaulB。是的,这是真的。三元运算符的参数是Nothing11 是一个整数,Nothing 也可以转换为整数(0),所以编译器很高兴并且知道三元运算符将返回一个整数。但是试试Dim i As Integer? = If(True, Nothing, "SomeString")。当Option Strict On时编译器会报错。
    • 好吧,我做到了definition.TestId = If(IsNothing(test), new Integer?, CType(test.Nodes(0).Value,Integer)),它可以工作,但必须编写很多代码,有什么优雅的解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多