在单行lambda表达式中使用函数而不是sub导致的错误

时间:2015-08-27 14:06:29

标签: .net vb.net lambda

我刚遇到一个同事写了一个错误的情况,尽管我们知道如何修复它,但我们并不理解它为什么会发生。我多年来一直在使用lamda表达式,但是对于C#比VB更有经验,我显然对某些东西有一个根本的误解。

在使用.Net 3.5的Visual Studio 2010中观察到以下内容。

我已将其简化为以下简单的测试代码,该代码再现了类似的场景:

在Windows窗体上,我将以下内容简单地执行lambda,然后将测试对象的值打印到文本框中:

Private Sub ExecuteAction(ByVal action As Action(Of TestClass))
    Dim testObj As New TestClass()
    action(testObj)
    TextBox1.Text = testObj.MyInteger
End Sub

Public Class TestClass
    Public MyInteger As Integer
End Class

然后我运行一些代码来使用lambda调用它。

在下面的例子中,文本框中的输出是15,正如我所料:

ExecuteAction(Sub(obj) obj.MyInteger = 15)

在下面的例子中,输出也是15,正如我所期望的那样(它确实会产生一个警告,因为没有指定返回值我理解并且没有,因为它可以达到预期效果):

ExecuteAction(Function(obj)
                 obj.MyInteger = 15
              End Function)

在以下情况中,输出为0,我不明白为什么:

ExecuteAction(Function(obj) obj.MyInteger = 15)

为什么在最终场景中对象的值不会变为15?我需要了解单行函数lambdas和多行函数lambdas之间的区别,看看我是否需要检查所有产品是否存在类似的bug。它编译良好,不会产生警告,使其对我们的使用极为危险。

我尝试了以下内容,看看它是否在任何隐式Return之前强制执行有任何区别,但它没有:

ExecuteAction(Function(obj) (obj.MyInteger = 15))

1 个答案:

答案 0 :(得分:9)

多行和单行函数之间的区别在于一个包含一个语句而另一个包含一个表达式。

obj.MyInteger = 15是一个语句时,=是赋值运算符。当它是表达式时,=是比较运算符。

单行功能的多行版本为:

ExecuteAction(Function(obj)
  Return obj.MyInteger = 15
End Function)

这将比较值并返回一个布尔值。由于预期Action(Of TestClass),因此不需要返回值的类型,因此您不会注意到它返回一个布尔值。