lambda表达式中对象的作用域
本文关键字:作用域 对象 表达式 lambda | 更新日期: 2023-09-27 18:18:08
我是c#新手,试图理解lambda表达式和委托。这是我正在运行的代码:
delegate bool D1();
delegate bool D2(int i);
namespace Console
{
class Program
{
D1 d1;
D2 d2;
public void testMethod(int input)
{
int j = 0;
d1 = () => { j = 10; return j < input; };
d2 = (x) => { return x == j; };
System.Console.WriteLine("j = {0}", j);
bool res = d1();
System.Console.WriteLine("res={0}, j ={1}", res, j);
}
static void Main(string[] args)
{
Program p = new Program();
p.testMethod(10);
System.Console.WriteLine(p.d2(10));
System.Console.ReadKey();
}
}
}
我不明白的是d2
的调用打印true
。构建d2
时,j
的值为0
。只有在testMethod
后面调用d1
之后才会更改它。那么它是如何打印True
?我错过了什么?
d1
和d2
都指向j
的同一个实例。当你通过调用d1
来设置j
时,你也改变了d2
可以看到的变量的值。
如果你想让它们有不同的j
实例,你需要定义变量的作用域:
{
int j = 0;
d1 = () => { j = 10; return j < input; };
}
{
int j = 0;
d2 = (x) => { return x == j; };
}
然而,如果你要这样做,那么你不妨有两个不同的变量,而不是说j1
和j2
。
当您创建委托时,它使用的范围之外的任何变量都将被捕获。在这种情况下,分配给d1
和d2
的委托都捕获了在testMethod()
中声明的变量j
;它们不创建j
的副本,它们捕获实际的变量。从这个意义上说,在d1
和d2
的生命周期内,j
在它们内部的行为就好像它是一个全局变量(当然,c#中没有全局变量这样的东西)。
如果您希望这些方法获得j
的单独实例,您需要为每个方法提供j
的副本,而不是仅仅使用它。例如:
public void testMethod(int input)
{
int j = 0;
int k = j;
d1 = () => { j = 10; return j < input; };
d2 = (x) => { return x == k; };
System.Console.WriteLine("j = {0}", j);
bool res = d1();
System.Console.WriteLine("res={0}, j ={1}", res, j);
}