我正在使用 VB.Net 分配一个委托。但是我不想定义方法(子)/函数。
简单地给予Nothing不起作用,因为DelegateCommand如果Nothing在委托中设置,则会引发运行时异常。
那么为什么我会收到这个错误呢?
"Single Line statements lambdas must include exactly one statement."
这是代码
Public Delegate Function DelegateCommand(Of T)(ByVal arg As T) As Boolean
Private _foobar As DelegateCommand(Of Object)
Public ReadOnly Property FooBar() As DelegateCommand(Of Object)
Get
If _foobar Is Nothing Then
_foobar = New DelegateCommand(Of Object)(Sub(), AddressOf OnFooBarCommandExecuted)
End If
Return _foobar
End Get
End Property
Private Function OnFooBarCommandExecuted(ByVal parameter As Object) As Boolean
Return False
End Function
Run Code Online (Sandbox Code Playgroud)
这是图像
VB.NET 编译器团队在将 lambda 表达式的支持硬塞到语言中时遇到了相当多的麻烦。用像 Basic 这样的古老的语言绝对不容易做到。您很难生成“最佳”诊断,语言解析器首先失败,因为必须将没有参数的 Sub() 与带有参数的 Function() 匹配。不能这样做,它不知道将什么作为函数参数值传递。更糟糕的是,它需要生成 MSIL 代码来清理堆栈并弹出函数返回值,但是您的 Sub() 说没有代码。这种差异使它大叫 Eeek!用糟糕的诊断和放弃。
在发现代码存在更根本的错误之前,它会尝试将两个方法传递给委托构造函数。你应该知道的更大的问题,不幸的是没有报告,因为它放弃了第一个错误。
Roslyn 项目值得注意,语言解析器被完全重写,它为这段代码生成了更好的诊断。集成到 VS2015 中,您现在可以获得:
错误 BC32008:委托“ConsoleApplication1.Example.DelegateCommand(Of Object)”需要“AddressOf”表达式或 lambda 表达式作为其构造函数的唯一参数。
这会让你在某个地方,注意作为错误消息中的唯一参数。正如错误消息中所暗示的那样,有两种方法可以做到这一点。有效的“AddressOf”表达式作为唯一参数:
_foobar = New DelegateCommand(Of Object)(AddressOf OnFooBarCommandExecuted)
Run Code Online (Sandbox Code Playgroud)
或者一个 lambda 表达式作为唯一的参数:
_foobar = New DelegateCommand(Of Object)(Function(parameter)
Return False
End Function)
Run Code Online (Sandbox Code Playgroud)
不再需要编写 OnFooBarCommandExecuted() 函数,您想要完成的工作。VB.NET 提供了大量的语法糖来进一步简化此代码。您可以声明 lambda 表达式不接受任何参数,即使委托声明了一个参数。而且您不必显式编写委托构造代码,编译器可以从_foobar变量中推断出它。将代码折叠为:
_foobar = Function() False
Run Code Online (Sandbox Code Playgroud)