我对C#比较陌生,所以如果这个问题的答案显而易见,我会道歉。
我写的程序的一部分存储了一个结构数组,结构的一个元素是一个curried函数。
以下是引起问题的代码部分(尽可能最小化)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CurryingProblem
{
class Program
{
public struct Value
{
public Func<decimal> Output;
}
public static decimal AddOne(decimal value)
{
return value + 1;
}
static void Main(string[] args)
{
Dictionary<string, Decimal> ThingsToAdd = new Dictionary<string, decimal>();
Dictionary<string, Value> ThingsToPrint = new Dictionary<string, Value>();
ThingsToAdd.Add("One", 1.0m);
ThingsToAdd.Add("Two", 2.0m);
foreach (KeyValuePair<string, Decimal> thing in ThingsToAdd)
{
Value value = new Value();
value.Output = () => AddOne(thing.Value);
ThingsToPrint.Add(thing.Key, value);
}
Console.WriteLine(ThingsToPrint["One"].Output());
Console.WriteLine(ThingsToPrint["Two"].Output());
Console.ReadKey();
}
}
}
该计划的预期输出是
2.0
3.0
但实际输出是
3.0
3.0
任何关于我出错的方向都会很棒。
答案 0 :(得分:3)
您的问题类似于 access to modified closure 。这article by Eric Lippert解释得非常好。您需要传递局部范围的变量而不是传递循环thing.Value。创建一个新变量并为其分配thing.Value,以便传递本地副本。
static void Main(string[] args)
{
Dictionary<string, Decimal> ThingsToAdd = new Dictionary<string, decimal>();
Dictionary<string, Value> ThingsToPrint = new Dictionary<string, Value>();
ThingsToAdd.Add("One", 1.0m);
ThingsToAdd.Add("Two", 2.0m);
foreach (KeyValuePair<string, Decimal> thing in ThingsToAdd)
{
Value value = new Value();
Decimal d = thing.Value;
value.Output = () => AddOne(d);
ThingsToPrint.Add(thing.Key, value);
}
Console.WriteLine(ThingsToPrint["One"].Output());
Console.WriteLine(ThingsToPrint["Two"].Output());
Console.ReadKey();
}