Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 闭包中的Foreach变量。为什么这些片段的结果不同?_C#_.net_Multithreading_Task - Fatal编程技术网

C# 闭包中的Foreach变量。为什么这些片段的结果不同?

C# 闭包中的Foreach变量。为什么这些片段的结果不同?,c#,.net,multithreading,task,C#,.net,Multithreading,Task,有人能解释一下为什么这段话: // Create required tasks foreach (var messageToSend in messagesToSend) { EmailMessage messageToBeSent = messageToSend; Task<bool> processingTask = new Task<bool>(() => SendMessage(messageToBeSent)); processingTask.

有人能解释一下为什么这段话:

// Create required tasks
foreach (var messageToSend in messagesToSend)
{
  EmailMessage messageToBeSent = messageToSend;
  Task<bool> processingTask = new Task<bool>(() => SendMessage(messageToBeSent));
  processingTask.Start();
}
//创建所需的任务
foreach(变量messageToSend in messagesToSend)
{
EmailMessageToSent=messageToSend;
任务处理任务=新任务(()=>SendMessage(messageToBeSent));
processingTask.Start();
}
工作原理与此不同:

// Create required tasks
foreach (var messageToSend in messagesToSend)
{
  Task<bool> processingTask = new Task<bool>(() => SendMessage(messageToSend));
  processingTask.Start();
}
//创建所需的任务
foreach(变量messageToSend in messagesToSend)
{
任务处理任务=新任务(()=>SendMessage(messageToSend));
processingTask.Start();
}
在第一个代码段中,所有任务都以自己的消息开头,而在第二个代码段中,所有任务都以相同的消息开头


Resharper给出了这样的描述:“访问闭包中的foreach变量。使用不同版本的编译器编译时可能会有不同的行为。”为什么会有不同的行为?

您的第二个代码示例有一个单个
,所有lambda表达式都在它们的闭包中捕获

代理运行时,将使用变量的当前值

Resharper给出了这样的描述:“访问闭包中的foreach变量。使用不同版本的编译器编译时,可能会有不同的行为。”为什么会有不同的行为

C#4和C#5之间有一个突破性的变化,这是因为foreach中的循环变量受到闭包的影响,特别是自从在C#3中引入lambda表达式以来。Resharper警告您这一点,以防您可能依赖于或以其他方式期待前面的语义

最快的结果是,在C#4中,循环变量在循环的每个迭代之间共享,闭包捕获变量,因此当大多数人关闭循环变量时,这会导致意外的结果

在C#5中,循环的每个迭代都有自己的变量,因此一个迭代中的闭包不会像其他迭代一样关闭同一个变量,从而导致更多的预期结果(对大多数人来说)

这让我们找到了你问题的核心:

在第一个代码段中,所有任务都以自己的消息开头,而在第二个代码段中,所有任务都以相同的消息开头

在第一个代码段中,您正在循环中创建循环变量的副本,并且闭包发生在内部变量上。在第二种情况下,直接关闭循环变量。假设您是在C#4下运行的,因此前面的语义适用。如果在C#5中运行,两个版本的循环输出应该是一致的。这就是Resharper所指的更改,它还应该让您了解如何用C#4构造代码(即,使用您编写的第一个版本)


正如Justin Pihony在评论中指出的那样,他写了一篇关于前一种语义学的文章,其中也提到了C#5的变化。

关于这个主题的问题每天都会在这里被问几次……试着对这个主题做一些研究,或者只是看看“相关的”谢谢你的简短回答,它解释了埃里克·利珀特所说的一切:有人能解释“C4”和“C5”是什么意思吗?我从来没听说过这个数字。它与.NET Framework 3.5、4.0和4.5有关吗?@RandyGamage