Vb.net 为什么这两个代码块存储不同的值?
设置: customObject是实体框架对象,customObject.is_required是一个可为空的字节字段,表示SQL Server中的一列,该列为tinyint并允许为空 ddlIsRequired是一个下拉列表,其中包含三个具有以下值的项: 空白 1表示是 0表示否 考虑以下代码:Vb.net 为什么这两个代码块存储不同的值?,vb.net,entity-framework,nullable,Vb.net,Entity Framework,Nullable,设置: customObject是实体框架对象,customObject.is_required是一个可为空的字节字段,表示SQL Server中的一列,该列为tinyint并允许为空 ddlIsRequired是一个下拉列表,其中包含三个具有以下值的项: 空白 1表示是 0表示否 考虑以下代码: customObj.is_required = If(String.IsNullOrEmpty(ddlIsRequired.SelectedValue), _
customObj.is_required = If(String.IsNullOrEmpty(ddlIsRequired.SelectedValue), _
Nothing, _
ddlIsRequired.SelectedValue)
执行时,上述代码行在可空字节字段customObj.is_中存储0
执行时,上面的代码块在customObj.is_required中不存储任何内容,这是我所期望的inline if所做的,然而inline if似乎将可空字节字段视为不可空,而是存储任何数字的默认值a零
这是为什么?原因是If函数必须返回具有给定类型的值。编译器通过查看返回值(第2个和第3个参数)的两个表达式来决定返回什么类型。在您的例子中,一个值为Nothing,另一个值为String。编译器决定可以不包含任何内容或字符串的最简单类型是字符串。如果选择的值为Nothing(无),则会将其转换为字符串;如果选择了Option Strict Off(这是一个坏主意),则在将字符串分配给Byte?时会将其转换为0
如果要在一条语句中执行此操作,则必须明确返回的表达式是一个字节
原因是If函数必须返回具有给定类型的值。编译器通过查看返回值(第2个和第3个参数)的两个表达式来决定返回什么类型。在您的例子中,一个值为Nothing,另一个值为String。编译器决定可以不包含任何内容或字符串的最简单类型是字符串。如果选择的值为Nothing(无),则会将其转换为字符串;如果选择了Option Strict Off(这是一个坏主意),则在将字符串分配给Byte?时会将其转换为0
如果要在一条语句中执行此操作,则必须明确返回的表达式是一个字节
正如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,因此编译器无法使用它来推断返回类型。然后,它查看第二个值,发现它是一个字符串,正如您在上面的注释中所述,SelectedValue属性被声明为字符串属性。因此,三元操作的返回类型将是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中,字节是什么?返回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,编译器将强制您以这种方式强制输入类型,否则它将无法编译:
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
正如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,因此编译器无法使用它来推断返回类型。然后,它查看第二个值,发现它是一个字符串,正如您在上面的注释中所述,SelectedValue属性被声明为字符串属性。因此,三元操作的返回类型将是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中,字节是什么?返回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,编译器将强制您以这种方式强制输入类型,否则它将无法编译:
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
顺便问一下,SelectedValue属性的类型是什么?这是对象还是字符串属性?SelectedValue始终返回字符串。是的,但属性的类型是什么?通过对象浏览器:公共可重写属性SelectedValue as String:摘要:获取列表控件中选定项的值,或选择列表控件中包含指定值的项。返回值:列表控件中选定项的值。默认值为空字符串。异常:System.ArgumentOutOfRangeException:所选值不在可用值列表中,并且已加载视图状态或其他状态。已执行回发。有关更多信息,请参阅备注部分
顺便问一下,SelectedValue属性的类型是什么?这是对象还是字符串属性?SelectedValue始终返回字符串。是的,但属性的类型是什么?通过对象浏览器:公共可重写属性SelectedValue as String:摘要:获取列表控件中选定项的值,或选择列表控件中包含指定值的项。返回值:列表控件中选定项的值。默认值为空字符串。异常:System.ArgumentOutOfRangeException:所选值不在可用值列表中,并且已加载视图状态或其他状态。已执行回发。有关更多信息,请参阅备注部分。是的,这现在是有意义的。遗憾的是,内联if对此如此紧张。问题回答了,谢谢!打开选项STRICT还不够,您可以强制If返回一个字节吗?如果你愿意的话。我编辑了我的答案来说明我是怎么做的。我只是对option strict做了一个评论,你的意思是向其他人提出这个问题吗,也许是OP?option strict确实是开着的。没有它你永远不会离开家。它甚至不应该是一个选项,但是,嘿,它是VB。是的,这现在是有意义的。遗憾的是,内联if对此如此紧张。问题回答了,谢谢!打开选项STRICT还不够,您可以强制If返回一个字节吗?如果你愿意的话。我编辑了我的答案来说明我是怎么做的。我只是对option strict做了一个评论,你的意思是向其他人提出这个问题吗,也许是OP?option strict确实是开着的。没有它你永远不会离开家。它甚至不应该是一个选项,但是,嘿,它是VB。