【问题标题】:Array of curried functions not acting properly咖喱函数数组不能正常工作
【发布时间】:2012-11-23 05:17:52
【问题描述】:

我对 C# 比较陌生,所以如果这个问题的答案很明显,我很抱歉。

我正在编写的程序的一部分存储结构数组,结构的元素之一是柯里化函数。

以下是导致问题的代码部分(尽可能减少)

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

任何关于我哪里出错的方向都会很棒。

【问题讨论】:

  • 真的吗?因为我的复制粘贴会产生2.03.0...
  • 是的,我的肯定会产生错误的值。我正在运行 Visual Studio 2008、.NET 3.5 SP1,如果这最终取决于版本

标签: c# lambda closures currying


【解决方案1】:

您的问题类似于 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();
    }

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
  • 2021-11-27
  • 2022-01-02
  • 2011-04-21
  • 2013-08-26
相关资源
最近更新 更多