Today I've witnessed some very strange behavior in VB.NET. The code I am talking about is the following:
Option Strict On
Option Explicit On
Module Module1
Sub Main()
Dim thisShouldBeSet = False
DoSomething(Function() thisShouldBeSet = True)
If Not thisShouldBeSet Then
Throw New Exception()
End If
Console.WriteLine("yaay")
End Sub
Sub DoSomething(action As Action)
action.Invoke()
End Sub
End Module
I know that the code in itself is flawed because I must use :
DoSomething(Sub() thisShouldBeSet = True)
Instead of:
DoSomething(Function() thisShouldBeSet = True)
But I find it very odd that even with Option Strict and Option Explicit On the compile allows me to compile this code.
What is even stranger is that when running the code the Action actually behaves like a Func(of Boolean).
Can anyone provide me with a valid explanation to why this is allowed in VB.NET? Is this a compiler / runtime bug?
Why should it not allow you to compile the code? thisShouldBeSet = True
is a valid comparison, returning the value False
(because thisShouldBeSet <> True
). Remember that =
in VB can mean both =
(assignment) and ==
(comparison) in C#, depending on the context.
To elaborate, Sub() thisShouldBeSet = True
would be a shorthand for
Sub Anonymous()
thisShouldBeSet = True ' Assignment
End Sub
whereas Function() thisShouldBeSet = True
is a shorthand for
Function Anonymous() As Boolean
Return thisShouldBeSet = True ' Comparison
End Sub
In VB, it is explicitly allowed to use a function with a return value as an Action. From the documentation of the System.Action delegate (highlighting by me):
In C#, the method must return void. In Visual Basic, it must be defined by the Sub…End Sub construct. It can also be a method that returns a value that is ignored.