How to declare lambda event handlers in VB.Net?

18,551

Solution 1

Note: This relates to older versions of VB.net Prior to Visual Studio 2010 and VB.net 10

The difference is that in VB.Net a lambda expression must return a value i.e. they must be functions not subs. The lambda expression eventRaised = true is being interpreted as a boolean expression rather than an assignment i.e. is evaluating to false rather than setting to true.

Further details on MSDN.

I'm don't think the c# pattern for testing events used in the example can be done in VB.Net without introducing another function e.g.

<TestFixture()> _
Public Class Test
    <Test()> _
    Public Sub EventTest()
        Dim eventClass As New EventClass
        Dim eventRaised As Boolean = False
        AddHandler eventClass.AnEvent, Function() (SetValueToTrue(eventRaised))
        eventClass.RaiseIt()
        Assert.IsTrue(eventRaised)
    End Sub

    Private Function SetValueToTrue(ByRef value As Boolean) As Boolean
        value = True
        Return True
    End Function

End Class

Public Class EventClass
    Public Event AnEvent()
    Public Sub RaiseIt()
        RaiseEvent AnEvent()
    End Sub
End Class

Solution 2

For those finding this question now: since Visual Basic 2010 (VB 10.0), anonymous Subs do work, so you can write something like:

Sub() eventRaised = True

Solution 3

Long story short, you cannot do that in VB for the time being (it is on the list of features considered for next release). You have to use a declared method and the AddressOf operator.

The VB team did not have the time to include anonymous delegates in the language (which is what you are trying to use, technically not a lambda expression).

Lambda expressions they had to implement so that Linq can actually work. Anonymous delegates are not required by anything (but would be quite useful). I guess they spent more time on wrapping up things like Linq To XML and XML litterals and integrating more query operators in the syntax...

Share:
18,551
Gareth D
Author by

Gareth D

15 years in the game and still learning ...

Updated on June 02, 2022

Comments

  • Gareth D
    Gareth D almost 2 years

    I believe the following VB.Net code is the equivalent of the proceeding C# code; however the VB.Net test fails - the event handling Lambda is never called.

    What is going on?

    VB.Net version - fails:

    <TestFixture()> _
    Public Class TestClass
        <Test()> _
        Public Sub EventTest()
            Dim eventClass As New EventClass
            Dim eventRaised As Boolean = False
            AddHandler eventClass.AnEvent, Function() (eventRaised = True)
            eventClass.RaiseIt()
            Assert.IsTrue(eventRaised)
        End Sub    
    End Class
    
    Public Class EventClass
        Public Event AnEvent()
        Public Sub RaiseIt()
            RaiseEvent AnEvent()
        End Sub
    End Class
    

    C# version - passes:

    [TestFixture]
        public class TestClass
        {
            [Test]
            public void EventTest()
            {
                var eventClass = new EventClass();
                var eventRaised = false;
                eventClass.AnEvent += () => { eventRaised = true; }; 
                eventClass.RaiseIt();
                Assert.IsTrue(eventRaised);
            }
        }
    
        public class EventClass
        {
            public delegate void EventHandler();
            public event EventHandler AnEvent;
            public void RaiseIt()
            {
                AnEvent();
            }
        }
    
  • chrissie1
    chrissie1 over 15 years
    They really screawed up with lambdas in VB.Net.
  • Gareth D
    Gareth D over 15 years
    Agreed, it seems they did the minimal to get link going and that was it.
  • Gareth D
    Gareth D over 15 years
    Understood that this is an anonymous delegate and not a lambda expression. However, is the following (which does work) an anonymous delegate in VB?: AddHandler eventClass.AnEvent, Function() (SetValueToTrue(eventRaised))
  • Evan Harper
    Evan Harper about 11 years
    Note that as of VS2010 VB.Net lambdas may now be subroutines and need not return a value.
  • Lei Yang
    Lei Yang almost 8 years
    What if more than one statement follow Sub()?
  • svick
    svick almost 8 years
    @LeiYang Then you can do: Sub() statement1 statement2 End Sub (it's four lines).