21

我相信下面的 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

4 回答 4

22

对于那些现在发现这个问题的人:自 Visual Basic 2010 (VB 10.0) 以来,匿名Subs 确实有效,因此您可以编写如下内容:

Sub() eventRaised = True
于 2013-01-06T14:15:30.220 回答
18

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

不同之处在于,在 VB.Net 中,lambda 表达式必须返回一个值,即它们必须是函数而不是子函数。lambda 表达式eventRaised = 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
于 2008-10-15T14:45:04.233 回答
2

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

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

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

于 2008-10-19T05:11:09.517 回答
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
于 2020-06-18T12:58:36.517 回答