Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bug caused by use of function instead of sub in single line lambda expression

I've just come across a situation where a colleague wrote a bug and we didn't understand why it happened despite the fact we know how to fix it. I've been using lamda expressions for years but am much more experienced with C# than VB and I obviously have a fundamental misunderstanding of something.

The following is observed in Visual Studio 2010 with .Net 3.5.

I've simplified this down to the following simple test code that reproduced a similar scenario:

On a windows form I put the following, to simply execute a lambda and then print the value of a test object to a textbox:

Private Sub ExecuteAction(ByVal action As Action(Of TestClass))
    Dim testObj As New TestClass()
    action(testObj)
    TextBox1.Text = testObj.MyInteger
End Sub

Public Class TestClass
    Public MyInteger As Integer
End Class

and then I run some code to call it using a lambda.

In the following case the output in the textbox is 15 as I would expect :

ExecuteAction(Sub(obj) obj.MyInteger = 15)

In the following case the output is also 15 as I would expect (it does generate a warning because no return value is specified which I understand and is fine because it does what is expected) :

ExecuteAction(Function(obj)
                 obj.MyInteger = 15
              End Function)

In the following case the output is 0 and I do not understand why:

ExecuteAction(Function(obj) obj.MyInteger = 15)

Why in the final scenario does the value of the object not change to 15? I need to understand this difference between single line function lambdas and multi line function lambdas to see if I need to check across all our products for similar bugs. It compiles fine and does not generate warnings making it extremely dangerous for our uses.

I tried the following to see if it made any difference forcing the execution before any implicit Return but it did not:

ExecuteAction(Function(obj) (obj.MyInteger = 15))
like image 445
Alan Macdonald Avatar asked Aug 27 '15 14:08

Alan Macdonald


1 Answers

The difference between the multi line and the single line functions is that one contains a statement and the other contains an expression.

When obj.MyInteger = 15 is a statement then = is the assignment operator. When it is an expression then = is the comparison operator.

The multi line version of your single line function is:

ExecuteAction(Function(obj)
  Return obj.MyInteger = 15
End Function)

This will compare the values and return a boolean value. As an Action(Of TestClass) is expected, there is no requirement on the type of the return value, so you don't notice that it returns a boolean value.

like image 134
Guffa Avatar answered Sep 30 '22 18:09

Guffa