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

VB.NET中的动作委托接受函数lambda表达式,vb.net,lambda,delegates,Vb.net,Lambda,Delegates,我有一个将动作委托作为参数的构造函数: 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() execut

我有一个将动作委托作为参数的构造函数:

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()。 但是,这不是事实,因为完全可以使用函数委托:

Dim executeIsCalled = False    
Dim command = New DelegateCommand(Function() executeIsCalled = True)
command.Execute(Nothing)
Assert.IsTrue(executeIsCalled) ' Fail
这可以很好地编译,但是
executeIsCalled=True
被解释为return语句,导致
executeIsCalled
仍然为false的意外结果。 有趣的是,您可以执行以下操作:

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

我怎样才能避免错误地使用了函数lambda表达式?

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

您可以使用
委托
而不是
操作
作为构造函数参数。不幸的是,VB.NET仍然允许任何其他开发人员传入
Sub()
Function()
lambdas。但是,您可以在运行时检查
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#世界,VB.NET-devs对它几乎一无所知。在这里,它用于编写没有返回值的方法(VB:Subs),就像任何其他返回值的方法(VB:Functions)一样


给出完整的代码(DelegateCommand类+命令实例化)。+p参数用于什么?我更新了问题第二个代码段(
Function()executeIsCalled=True
)是一个lambda表达式,而第三个代码段(
Function()…End Function
)是一个匿名函数,这是两个不同的东西谢谢Alex,我没有意识到这一点,我怀疑是否可能只允许Sub()和不允许Function()。请把这当作一个猜测,因为我没有证据:只有在VB语法(Sub(),Function())中,才可以注意到lambda有返回值和没有返回值之间的区别。在C语言中,你没有这种区别,在这两种情况下都是这样的
()=>executeIsCalled=true)。当检查动作方法或功能方法时,我没有观察到任何差异。我编写了一个小测试程序,并用C#在这两种情况下executeIsCalled=true。似乎只有.NET优步专业版才能回答这个问题;)
private void MySub() 
{
    // ...
}

private bool MyFunction()
{
    return true;
}