设置:
customObject
是一个Entity Framework对象,customObject.is_required
是一个可以为空的字节字段,表示SQL Server中tinyint
的一列,并允许空值。
ddlIsRequired
是一个下拉列表,其中包含三个具有以下值的项目:
""
(空白)
"1"
("是")
"0"
(" no")
请考虑以下代码:
customObj.is_required = If(String.IsNullOrEmpty(ddlIsRequired.SelectedValue), _
Nothing, _
ddlIsRequired.SelectedValue)
执行时,上面的代码行在可空字节字段customObj.is_required
If String.IsNullOrEmpty(ddlIsRequired.SelectedValue) Then
customObj.is_required = Nothing
Else
customObj.is_required = ddlIsRequired.SelectedValue
End If
执行时,上面的代码块将Nothing
存储在customObj.is_required
中,这是我原本期望的内联 - 如果已经完成,但是内联 - if似乎对待{{1} }}字段,好像它不可为空,而是存储任何数字的默认值(零)。
为什么会这样?
答案 0 :(得分:3)
原因是If
函数必须返回给定类型的值。编译器通过查看返回值的两个表达式(第二个和第三个参数)来决定返回什么类型。在您的情况下,一个值为Nothing
,另一个值为String。编译器决定可以包含Nothing
或String的最简单类型是String。如果选择的值为Nothing
,则将其转换为字符串(""),如果您有Option Strict Off
(这是一个坏主意),则字符串"& #34;将其分配给字节时转换为0。
如果您想在一个语句中执行此操作,则必须明确返回的表达式为Byte?
customObj.is_required = If(String.IsNullOrEmpty(ddlIsRequired.SelectedValue), Nothing, CType(ddlIsRequired.SelectedValue, Byte?))
答案 1 :(得分:2)
正如Blackwood所述,编译器通过检查最后两个参数的类型自动推断出三元If
操作的返回类型。例如:
Dim test As Object = If(True, "1", "2")
Console.WriteLine(test.GetType().Name) ' Outputs "String"
Dim test2 As Object = If(True, 1, 2)
Console.WriteLine(test.GetType().Name) ' Outputs "Int32"
在您的情况下,第一个值是Nothing
,因此编译器不能使用它来推断返回类型。然后它查看第二个值并看到它是String
(正如您在上面的注释中所述,SelectedValue
属性被声明为String
属性)。因此,三元操作的返回类型将为String
。
因此,当它返回Nothing
时,它会将其作为String
类型返回,然后将其转换为可空字节。换句话说,从长远来看,它是这样做的:
Dim input As String = ddlIsRequired.SelectedValue
Dim stringOutput As String = Nothing
If String.IsNullOrEmpty(input) Then
stringOutput = Nothing
Else
stringOutput = input
End If
Dim output As Byte? = CType(output, Byte?)
customObj.is_required = output
而且,因为在VB CType("", Byte?)
中返回0,那就是你得到的。您仍然可以使用三元If
运算符,只要您将其强制转换为正确的类型:
customObj.is_required = If(String.IsNullOrEmpty(ddlIsRequired.SelectedValue), Nothing, CType(ddlIsRequired.SelectedValue, Byte?))
其中,长篇形式,如下所示:
Dim input As String = ddlIsRequired.SelectedValue
Dim inputNullableByte As Byte? = CType(input, Byte?)
Dim output As Byte? = Nothing
If String.IsNullOrEmpty(input) Then
output = Nothing
Else
output = inputNullableByte
End If
customObj.is_required = output
正如其他人所说,通过转动Option Strict On
,编译器会强制你以这种方式强制输入类型,否则就不会编译:
Option Strict On
' ...
Dim output As Byte? = If(True, Nothing, "1") ' Compiler error BC30512 Option Strict On disallows implicit conversions from 'String' to 'Byte?'
鉴于:
Option Strict Off
' ...
Dim output As Byte? = If(True, Nothing, "1") ' Works and output gets set to 0