1

I detected a strange behavior in the on line If statement in VB.Net

If you check this code: jdoodle.com/a/X20

Imports System

Public Class Test
    Public Shared Sub Main()
        Dim x as Integer?

        Dim ob1 As Objeto = New Objeto()
        ob1.Valor = 1
        Dim obnull As Objeto = Nothing

        x = If(obnull Is Nothing, Nothing, obnull.Valor)

        System.Console.WriteLine(x)

        If Not obnull Is Nothing Then
            x = obnull.Valor
        Else
           x = Nothing
        End If

        System.Console.WriteLine(x)


    End Sub
End Class

Public Class Objeto
    Public Valor As Integer
End Class

It returns 0 in the x = If(obnull Is Nothing, Nothing, obnull.Valor) statement instead of a null value.

Why?

rasputino
  • 691
  • 1
  • 8
  • 24

1 Answers1

3

There's nothing strange about that behaviour. The If operator is effectively generic, i.e. the return type is inferred from the common type of the second and third arguments. The third argument is type Integer and Nothing can be interpreted as type Integer too so it is. Nothing as an Integer is zero so that's what you get. If you want If to return an Integer? then at least one of the arguments needs to be that type and the other must be able to be interpreted as that type.

Dim obj As Object
Dim int = 100

Dim result1 = If(obj Is Nothing, Nothing, int)
Dim result2 = If(obj Is Nothing, DirectCast(Nothing, Integer?), int)
Dim result3 = If(obj Is Nothing, Nothing, New Integer?(int))

In that code, result1 is type Integer and will be equal to zero while both result2 and result3 will be type Integer? and will both have no value.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • It's little bit strange for those who are comparing VB.NET with C#. `Nothing` in VB also means `default(t)`(in C#) so returns the default value of a given type. – Tim Schmelter Feb 01 '19 at 09:05
  • Yes, I fixed with x = If(obnull Is Nothing, New Integer?, obnull.Valor) but I couldn't figure it out. Thanks! – rasputino Feb 01 '19 at 09:05
  • @Rango, I'll grant that it may seem strange to those who don't realise that `Nothing` in VB is subtly different to `null` in C# but the behaviour is perfectly logical from a VB perspective. – jmcilhinney Feb 01 '19 at 09:08
  • 1
    @jmcilhinney: perfectly logical for the language designers and for those who are only developing with VB.NET. If you have a `Nullable(Of Int32)` and you assign `Nothing` you expect it to be `Nothing` and not `0`. In my opinion the "default-value-feature" of `Nothing` causes a lot of confusion here. It allows an implicit "conversion" between `Int32` and `Nothing` which is not `Int32?` but `0`. – Tim Schmelter Feb 01 '19 at 09:13
  • @Rango, firstly, VB has no responsibility to those who don't know how to use VB properly and want it to work like some other language that they are using. As for your wanting a `Nullable(Of Int32)` to be `Nothing` if you assign `Nothing` to it, that is exactly what you get so you're complaining about something you clearly don't understand. In the original code, the problem is that it is NOT `Nothing` that is being assigned to the variable. It is zero that is being assigned and so that's what the variable is equal to. – jmcilhinney Feb 01 '19 at 09:22
  • @Rango, like I said, the `If` operator is effectively generic so its return type is determined by its last two arguments. In the original code, the appropriate interpretation of those two arguments is that they are type `Integer` and so that is the return type of that `If` operator. If the return type is `Integer` then `Nothing` as no object is simply not a possible return value so how could no object be assigned to a variable from it? – jmcilhinney Feb 01 '19 at 09:25
  • @jmcilhinney: of course Microsoft has the responsibility to provide a similar behavior in their own .NET languages especially because many switch or convert between VB.NET and C#. This question is asked often and i wonder how many programs still contain (undetected) bugs because of the different behavior. – Tim Schmelter Feb 01 '19 at 09:30
  • 1
    @jmcilhinney: i know what happens, the reason for the behavior. That's not the point. Once you know that `Nothing` means `0` this is perfectly logical. But for 99% `Nothing` doesn't mean 0 even if you use it in a conditional operator with another `Int32`. Of course the compiler doesn't look at the variable that you want to assign the result(`Nullable(Of Int32)`), but people do. That's my point, this behavior is not intuitive and causes confusion for many. It's begging for bugs, the compiler could be clever enough to warn that you are going to use this `Nothing` as `0`. – Tim Schmelter Feb 01 '19 at 09:36
  • Personally, I think that people should take responsibility for learning the language they want to code in. If people are too lazy to read, they deserve what they get. *"This question is asked often"*. Yeah, and the documentation is consulted rarely. – jmcilhinney Feb 01 '19 at 10:11