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

22
我相信以下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个回答

24

对于现在看到这个问题的人:自从 Visual Basic 2010(VB 10.0)以后,匿名Sub是可以工作的,因此您可以编写类似以下内容的代码:

自从 Visual Basic 2010(VB 10.0)以后,您可以编写类似以下内容的代码:

Sub() eventRaised = True

如果Sub()后面跟着多个语句会怎么样? - Lei Yang
3
@LeiYang 然后你可以这样做:Sub() statement1 statement2 End Sub(总共四行)。 - svick

18

注意:这与VB.net 2010和VB.net 10以前的版本有关。

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

有关更多详细信息,请参阅MSDN

我认为在VB.Net中使用示例中所示的测试事件的C#模式是不可能的,除非引入另一个函数。

<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

16
他们在 VB.Net 中的 lambda 函数中搞砸了。 - chrissie1
同意,看起来他们只是尽最小的努力让链接正常工作,然后就没再管了。 - Gareth D
4
请注意,自VS2010起,VB.Net的lambda表达式现在可以是子程序,不需要返回任何值。 - Evan Harper

2
长话短说,目前你不能在VB中实现此功能(该功能已列入下一版本考虑的功能列表)。您必须使用已声明的方法和AddressOf运算符。
VB团队没有时间将匿名委托包含在语言中(技术上不是lambda表达式,这就是您尝试使用的内容)。
他们必须实现Lambda表达式,以便Linq可以正常工作。匿名委托不需要任何东西(但会非常有用)。我想他们花了更多的时间来封装诸如Linq To XML和XML litterals之类的东西,并在语法中集成更多的查询操作符...

理解这是匿名委托而不是lambda表达式。然而,下面的代码(可以工作)在VB中是匿名委托吗?AddHandler eventClass.AnEvent, Function() (SetValueToTrue(eventRaised)) - Gareth D

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接