【问题标题】:Action delegate in VB.NET accepts a function lambda expressionVB.NET 中的动作委托接受函数 lambda 表达式
【发布时间】:2015-12-02 11:04:49
【问题描述】:

我有一个将 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

Action 没有返回值,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 仍然是 false。 有趣的是,您可以执行以下操作:

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

如何防止错误地使用了 Function lambda 表达式?

【问题讨论】:

  • 给出完整代码(DelegateCommand 类 + 命令实例化)。 + p 参数是干什么用的?
  • 我更新了问题
  • 第二个 sn-p (Function() executeIsCalled = True) 是一个 lambda 表达式,而第三个 sn-p (Function () ... End Function) 是一个匿名函数,它们是两个不同的东西
  • 谢谢 Alex,我不知道
  • 不过,我怀疑是否可以只允许 Sub() 而不允许 Function()。请将此作为猜测,因为我没有证据证明:带和不带返回值的 lambda 之间的区别仅在 VB 语法(Sub()、Function())中很明显。在 C# 中,您没有这种区别() => executeIsCalled = true);。检查 Action.Method 或 Function.Method 时,我无法观察到任何差异。我编写了一个小测试程序,并在两种情况下都使用 C# 执行 IsCalled = true。看来这只能由 .NET uber pro 来回答;)

标签: vb.net lambda delegates


【解决方案1】:

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

您可以使用Delegate 而不是Action<> 作为构造函数参数。不幸的是,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 开发人员大多不知道。在那里,它用于编写没有返回值的方法(VB:Subs),就像任何其他返回值的方法(VB:Functions)一样。

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

private bool MyFunction()
{
    return true;
}

【讨论】:

    猜你喜欢
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 2012-06-14
    相关资源
    最近更新 更多