如何在VB.Net中声明lambda事件处理程序?

时间:2008-10-15 13:57:22

标签: c# vb.net unit-testing events lambda

我相信以下VB.Net代码相当于正在进行的C#代码;但是VB.Net测试失败 - 从不调用处理Lambda的事件。

发生了什么事?

VB.Net版本 - 失败:

<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#版本 - 传递:

[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();
        }
    }

4 个答案:

答案 0 :(得分:17)

对于那些现在发现这个问题的人:从Visual Basic 2010(VB 10.0)开始,匿名Sub可以正常工作,所以你可以这样写:

Sub() eventRaised = True

答案 1 :(得分:16)

  

注意:这与Visual Studio 2010和VB.net 10之前的旧版VB.net有关

不同之处在于,在VB.Net中,lambda表达式必须返回一个值,即它们必须是函数而不是subs。 lambda表达式eventRaised = true被解释为布尔表达式而不是赋值,即评估为false而不是设置为true。

MSDN的详细信息。

我不认为示例中使用的测试事件的c#模式可以在VB.Net中完成,而不会引入另一个函数,例如。

<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

答案 2 :(得分:2)

长话短说,暂时不能在VB中这样做(它在下一版本考虑的功能列表中)。您必须使用声明的方法和AddressOf运算符。

VB团队没有时间在语言中包含匿名委托(这是您尝试使用的,技术上不是lambda表达式)。

他们必须实现Lambda表达式,以便Linq可以实际工作。任何事情都不要求匿名代表(但是非常有用)。我猜他们花了更多的时间来整理像Linq To XML和XML litterals这样的东西,并在语法中集成更多的查询运算符......

答案 3 :(得分:0)

具有弹出窗口的WPF控件需要WPF应用程序对象的实例。在WPF应用程序中,这是自动创建的。在WinForm应用程序中不是这种情况。因此,必须手动创建该对象。还必须将应用程序设置为保持打开状态,直到通过代码关闭它为止;否则,当WinForm应用程序确定不再需要它时,它将自动关闭。下面的代码将在WinForm中打开Application对象,并将其保持打开状态直到关闭。建议在WinForm关闭时关闭Application对象。

  Dim app As System.Windows.Application = New System.Windows.Application With {
            .ShutdownMode = Windows.ShutdownMode.OnExplicitShutdown
        }
        AddHandler Closed, Sub()
                               app.Shutdown()
                           End Sub