2012-11-23 7 views
1

저는 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

정말요? 내 복사하여 붙여 넣기 때문에'2.0'과'3.0'이 생성됩니다 ... –

+0

그래, 제 잘못 확실히 잘못된 값을 생성합니다. Visual Studio 2008, .NET 3.5 SP1을 실행 중이며 버전 종속성이있는 경우 – JamesL

답변

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(); 
    } 
+0

이 기능이 작동합니다. 감사합니다. 나는 이것이 범위의 미묘함을 이해하지 못하는 것 때문에 내게 종기라고 생각한다. – JamesL

+0

이 기사는 이해하기에 매우 유용합니다. http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx – Adil

+0

+1 설명. –

관련 문제