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

发布于 2024-07-07 21:15:13 字数 1245 浏览 7 评论 0原文

我相信以下 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();
        }
    }

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

动听の歌 2024-07-14 21:15:13

对于现在发现这个问题的人:从 Visual Basic 2010 (VB 10.0) 开始,匿名 Sub 可以工作,因此您可以编写如下内容:

Sub() eventRaised = True

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
静水深流 2024-07-14 21:15:13

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

区别在于,在 VB.Net 中,lambda 表达式必须返回一个值,即它们必须是函数而不是 subs 。 lambda 表达式 eventRaished = 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

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
虚拟世界 2024-07-14 21:15:13

长话短说,您暂时无法在 VB 中执行此操作(它在下一版本考虑的功能列表中)。 您必须使用声明的方法和 AddressOf 运算符。

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

他们必须实现 Lambda 表达式,这样 Linq 才能真正工作。 任何事情都不需要匿名代表(但非常有用)。 我猜他们花了更多的时间来包装 Linq To XML 和 XML 文本之类的东西,并在语法中集成更多的查询运算符......

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...

め七分饶幸 2024-07-14 21:15:13

具有弹出窗口的 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

WPF controls that have popups require an instance of the WPF Application Object. In a WPF application, this is automatically created. This is not the case in a WinForm application. For this reason, this object must be created manually. The Application also must be set to remain open until it is shut down through code, otherwise it will shut automatically when the WinForm applications determines it is no longer needed. The following code will open the Application object in a WinForm and keep it open until it is closed. Shutting down the Application object when the WinForm closes is the recommended approach.

  Dim app As System.Windows.Application = New System.Windows.Application With {
            .ShutdownMode = Windows.ShutdownMode.OnExplicitShutdown
        }
        AddHandler Closed, Sub()
                               app.Shutdown()
                           End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文