VB.NET中的Action委托接受函数lambda表达式

时间:2015-12-02 11:04:50

标签: vb.net lambda delegates

我有一个构造函数,它将Action委托作为参数:

Public Class DelegateCommand
    Public Sub New(execute As Action(Of T))
        Me.New(execute, Nothing)
    End Sub
End Command

' This works as expected
Dim executeIsCalled = False
Dim command = New DelegateCommand(Sub() executeIsCalled = True)
command.Execute(Nothing)
Assert.IsTrue(executeIsCalled) ' Pass

操作没有返回值,MSDN声明我必须为此目的使用Sub(MSDN Action Delegate)。 但事实并非如此,因为完全可以使用函数委托:

Dim executeIsCalled = False    
Dim command = New DelegateCommand(Function() executeIsCalled = True)
command.Execute(Nothing)
Assert.IsTrue(executeIsCalled) ' Fail

这编译得很好,但是executeIsCalled = True被解释为return语句,导致executeIsCalled保持为假的意外结果。 有趣的是,您可以执行以下操作:

Dim executeIsCalled = False
Dim command = New DelegateCommand(Function()
                                          executeIsCalled = True
                                          Return False
                                      End Function)
command.Execute(Nothing)
Assert.IsTrue(executeIsCalled) ' Pass

如何预先错误地使用函数lambda表达式?

1 个答案:

答案 0 :(得分:2)

这可能无法完美地解决您的需求,因为编译器不会帮助您 - 但至少您会在运行时发现错误,并且不知道为什么没有正确设置任何变量。

您可以使用Delegate而不是Action<>作为构造函数参数。不幸的是,VB.NET仍然允许任何其他开发人员传入Sub()Function() lambda。但是,您可以在运行时检查ReturnType,如果不是Void则抛出异常。

Public Class DelegateCommand
    Public Sub New(execute As [Delegate])

        If (Not execute.Method.ReturnType.Equals(GetType(Void))) Then
            Throw New InvalidOperationException("Cannot use lambdas providing a return value. Use Sub() instead of Function() when using this method in VB.NET!")
        End If

        execute.DynamicInvoke()
    End Sub
End Class

Void来自C#-world,而VB.NET-devs大多都不知道。在那里,它用于编写没有返回值的方法(VB:Subs),就像任何其他返回值的方法一样(VB:Functions)。

private void MySub() 
{
    // ...
}

private bool MyFunction()
{
    return true;
}