Reputation: 999
I'm using Nullable(Of Integer)
and have just been stung by Nothing
being cast to 0. That's excatly what I don't want when using Nullable(Of Integer)
.
func1
below doesn't behave as I'd expect. I can get it to do my will by ammending it (see func2
). But I don't see why this should be necessary (and I think I might find it hard to remember to do it).
Why isn't func1
doing what I want? I think I've encountered this before, and I'd rather not see it again.
Function func1(parameter As Integer) As Nullable(Of Integer)
Return If(parameter > 10, parameter, Nothing)
End Function
Function func2(parameter As Integer) As Nullable(Of Integer)
Return If(parameter > 10, parameter, DirectCast(Nothing, Integer?))
End Function
Sub Main
' Should be True
System.Console.WriteLine(func1(11).HasValue)
System.Console.WriteLine(func2(11).HasValue)
System.Console.WriteLine()
' Should be False
System.Console.WriteLine(func1(9).HasValue)
System.Console.WriteLine(func2(9).HasValue)
End Sub
The results I get (running this in LINQPad) are:
True
True
True
False
Upvotes: 0
Views: 65
Reputation: 11773
Here is func1 rewritten. Note that there is no need for casting.
Function func1(parameter As Integer) As Nullable(Of Integer)
Dim rv As New Nullable(Of Integer)
If parameter > 10 Then
rv = parameter
End If
Return rv
End Function
The If operator, If(foo,foo=true,foo=false), should be used sparingly because it is slower than the standard If construct.
edit: The statement about the If operator is incorrect.
Thanks to Chris.
Upvotes: 0
Reputation: 1883
To explain what is happening here, I'll start by removing the shorthand part of your code which may help with my explanation.
Integers in VB.net cannot be assigned using Null
or DBNull
. IT can be assigned using Nullable-of-T as you have. However, as soon as you make the object Nullable-ish, it can be evaluated to be 0.
Consider the following
dim x as Integer = nothing 'evaluates to x=0
So when your function runs, you use DirectCast()
to return a nullable-ish Integer, which then evaluates to be not nullable by func2
Function func1(parameter As Integer) As Nullable(Of Integer)
Return If(parameter > 10, parameter, Nothing)
End Function
Function func2(parameter As Integer) As Nullable(Of Integer)
Return If(parameter > 10, parameter, DirectCast(Nothing, Nullable(of Integer)))
End Function
Sub Main()
' Should be True
System.Console.WriteLine(func1(11).HasValue)
System.Console.WriteLine(func2(11).HasValue)
System.Console.WriteLine()
' Should be False
System.Console.WriteLine(func1(9).HasValue)
System.Console.WriteLine(func2(9).HasValue)
Console.ReadLine()
End Sub
Upvotes: 1
Reputation: 32445
Facts important in your case:
If
method expected that both "true" and "false" expressions
must return same type.Nothing
is default value of type.Integer
it is 0
.null
In first method inline If
method expects that "False" expression must return an Integer
, because compiler cannot decide return type based on Nothing
, it will use type produced by "True" expression. So Nothing
will produce default value of Integer
type which is 0
.
In second method both parameters have explicitly declared returned types, where Integer
can be implicitly converted to the Nullable
, so compiler will return Nullable as result of If
method.
The key role in your problem is inline If
method. Which uses Nothing
as default value of Integer
.
If you rewrite it as normal If .. Else
then everything works without DirectCast
Private Function GetNullableInteger(parameter As Integer) As Integer?
If parameter > 10 Then
Return parameter
Else
Return Nothing
End If
End Function
Upvotes: 2