question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

VB.NET ".?" Syntax OR GreaterThan Breaking Change

See original GitHub issue

Version Used: Somewhere between the version in msbuild 16.1 and 16.7

Steps to Reproduce:

Code example:

Sub Main()

        Dim map As Map = Nothing

        Console.WriteLine($"1 (Expect Empty): {IsHit(map, 0, 0)}")

        map = New Map() With {.Positions = Nothing}

        Console.WriteLine($"2 (Expect Empty): {IsHit(map, 0, 0)}")

        map = New Map() With {.Positions = New List(Of List(Of String))()}
        map.Positions.Add(Nothing)

        Console.WriteLine($"3 (Expect Empty): {IsHit(map, 0, 0)}")

        map = New Map() With {.Positions = New List(Of List(Of String))()}
        map.Positions.Add(New List(Of String)())
        map.Positions(0).Add(Nothing)

        Console.WriteLine($"4 (Expect Empty): {IsHit(map, 0, 0)}")

        map = New Map() With {.Positions = New List(Of List(Of String))()}
        map.Positions.Add(New List(Of String)())
        map.Positions(0).Add("")

        Console.WriteLine($"5 (Expect Miss): {IsHit(map, 0, 0)}")

        map = New Map() With {.Positions = New List(Of List(Of String))()}
        map.Positions.Add(New List(Of String)())
        map.Positions(0).Add("X")

        Console.WriteLine($"6 (Expect Hit): {IsHit(map, 0, 0)}")

        Console.ReadLine()

    End Sub

    Function IsHit(map As Map, x As Integer, y As Integer) As String

        Try
            If map?.Positions?.Count() > x AndAlso map.Positions(x)?.Count() > y AndAlso Not map.Positions(x)(y) Is Nothing Then

                If map.Positions(x)(y).Equals("X", StringComparison.InvariantCultureIgnoreCase) Then
                    Return "Hit"
                Else
                    Return "Miss"
                End If
            Else
                Return "Empty"
            End If
        Catch ex As Exception
            Return $"Error - {ex.Message}"
        End Try

    End Function

    Class Map

        Public Property Positions As List(Of List(Of String))

    End Class

Expected Behavior:

Output:

1 (Expect Empty): Empty
2 (Expect Empty): Empty
3 (Expect Empty): Empty
4 (Expect Empty): Empty
5 (Expect Miss): Miss
6 (Expect Hit): Hit

Actual Behavior:

Output:

1 (Expect Empty): Error - Object reference not set to an instance of an object.
2 (Expect Empty): Error - Object reference not set to an instance of an object.
3 (Expect Empty): Error - Object reference not set to an instance of an object.
4 (Expect Empty): Empty
5 (Expect Miss): Miss
6 (Expect Hit): Hit

When running code compiled using an older version of the compiler, the map?.Positions?.Count() > x AndAlso map.Positions(x)?.Count() > y AndAlso Not map.Positions(x)(y) Is Nothing If check will return False and the output is as expected. However, on newer versions, this same if will throw a null reference exception.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:26 (14 by maintainers)

github_iconTop GitHub Comments

2reactions
jaredparcommented, Nov 28, 2020

Sorry missed this issue. The change which caused this difference is #38802.

The core issue here is that the result of AndAlso in VB when dealing with nullable values is not just True and False but can also contain the result Nothing. Specifically it means that CType(Nothing, Nullable(Of Boolean) AndAlso False produces the value False. That means that in the case of nullable operations VB is not short circuiting when the left hand side returns Nothing. It must evaluate the right hand side to understand the return.

This has been the design of VB since nullable values were introduced. Unfortunately an optimization bug slipped into the compiler which caused this logic to not be consistently applied to user code. As a result it was hard for customers to predict how their programs would work and hard for us to maintain the broken logic here. After several attempts to maintain the logic we decided it was better to fix the optimization bug.

This does mean that AndAlso is not necessarily short circuiting when nullable values are involved (that has been true though since nullable was added). The code in this case needs to guard against map being Nothing in all of the branches of AndAlso.

Sharp lab demo of the behavior

1reaction
CyrusNajmabadicommented, Sep 11, 2020

But the problem now is how the Equals operator works.

Will need investigation on the VB side about this. At first glance it seems wrong.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Visual Basic breaking changes in .NET Core 3.0
The following is a list of breaking changes in Visual Basic: Types in Microsoft.VisualBasic.ApplicationServices namespace not available ...
Read more >
How to: Break and Combine Statements in Code - Visual ...
In the following example, the statement is broken into four lines with line-continuation characters terminating all but the last line. Using ...
Read more >
vb.net Add Watch stop when value changes
You can right click on a break point and then choose Condition. In the condition box type the name of the variable and...
Read more >
An Exhausting List of Differences Between VB.NET & C# | ...
This is NOT a list of syntax differences between VB and C# (of which there are countless). I'll mostly be talking about semantic...
Read more >
Visual Basic (VB.NET) – Full Course for Beginners - YouTube
Lean the fundamentals of programming with Visual Basic (sometimes called ... how to write code to validate and process the data collected.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found