我刚刚遇到一个同事写了一个错误的情况,尽管我们知道如何修复它但我们不明白它为什么会发生.我多年来一直在使用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))
多行和单行函数之间的区别在于一个包含一个语句而另一个包含一个表达式.
当obj.MyInteger = 15是一个语句时,= =是赋值运算符.当它是表达式时,则=是比较运算符.
单行功能的多行版本是:
ExecuteAction(Function(obj) Return obj.MyInteger = 15 End Function)
这将比较值并返回一个布尔值.由于Action(Of TestClass)是预期的,因此不需要返回值的类型,因此您不会注意到它返回一个布尔值.