我有一个构造函数,它将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表达式?
答案 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;
}