問題描述
考慮以下代碼:
公共類 MyClass{公共委托字符串 PrintHelloType(字符串問候語);公共無效執(zhí)行(){Type[] types = new Type[] { typeof(string), typeof(float), typeof(int)};列表<PrintHelloType>helloMethods = 新列表<PrintHelloType>();foreach(類型中的 var 類型){var sayHello =new PrintHelloType(greeting => SayGreetingToType(type, greeting));helloMethods.Add(sayHello);}foreach(helloMethods 中的 var helloMethod){Console.WriteLine(helloMethod("Hi"));}}public string SayGreetingToType(Type type, string greetingText){返回 greetingText + " " + type.Name;}...}
調(diào)用myClass.Execute()
后,代碼打印出以下意外響應(yīng):
顯然,我希望 "Hi String"
、"Hi Single"
、"Hi Int32"
,但顯然不是案件.為什么在所有 3 種方法中都使用迭代數(shù)組的最后一個元素而不是適當(dāng)?shù)姆椒?
您將如何重寫代碼以實(shí)現(xiàn)預(yù)期目標(biāo)?
歡迎來到閉包和捕獲變量的世界:)
Eric Lippert 對此行為有深入的解釋:
- 結(jié)束在被認(rèn)為有害的循環(huán)變量上
- 結(jié)束在循環(huán)變量上,第二部分
基本上,捕獲的是循環(huán)變量,而不是值.要獲得您認(rèn)為應(yīng)該獲得的東西,請執(zhí)行以下操作:
foreach (var type in types){var newType = 類型;var sayHello =new PrintHelloType(greeting => SayGreetingToType(newType, greeting));helloMethods.Add(sayHello);}
Consider the following code:
public class MyClass
{
public delegate string PrintHelloType(string greeting);
public void Execute()
{
Type[] types = new Type[] { typeof(string), typeof(float), typeof(int)};
List<PrintHelloType> helloMethods = new List<PrintHelloType>();
foreach (var type in types)
{
var sayHello =
new PrintHelloType(greeting => SayGreetingToType(type, greeting));
helloMethods.Add(sayHello);
}
foreach (var helloMethod in helloMethods)
{
Console.WriteLine(helloMethod("Hi"));
}
}
public string SayGreetingToType(Type type, string greetingText)
{
return greetingText + " " + type.Name;
}
...
}
After calling myClass.Execute()
, the code prints the following unexpected response:
Hi Int32 Hi Int32 Hi Int32
Obviously, I would expect "Hi String"
, "Hi Single"
, "Hi Int32"
, but apparently it is not the case. Why the last element of the iterated array is being used in all the 3 methods instead of the appropriate one?
How would you rewrite the code to achieve the desired goal?
Welcome to the world of closures and captured variables :)
Eric Lippert has an in-depth explanation of this behaviour:
- Closing over the loop variable considered harmful
- Closing over the loop variable, part two
basically, it's the loop variable that is captured, not it's value. To get what you think you should get, do this:
foreach (var type in types)
{
var newType = type;
var sayHello =
new PrintHelloType(greeting => SayGreetingToType(newType, greeting));
helloMethods.Add(sayHello);
}
這篇關(guān)于在 lambda 表達(dá)式中使用 foreach 循環(huán)的迭代器變量 - 為什么會失敗?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!