Monday, July 14, 2008

I ain't gettin' paid enough for this...

Remember when I said I'm not exactly great with programming terms? Well if I didn't, I am saying it now. So I saw the word "closures" today and had no idea what this was. All excited about something new, I found out that closures is just another word for anonymous methods, although it may include stuff outside that scope but I'm not sure. Anyhow, although this seemed to be yet another attack of the stupid I stumbled across something here. Basically what caught me is how value types are handled with Funcs. Take this method:
using System;
using System.Collections.Generic;
using System.Linq;

public static Func<Int32> ReturnIntegerWithinFuncReturningMethod(WhichMethod methodToReturn)
{
  Int32 integerToIncrement;
  Func<Int32> returnMethod;
  
  integerToIncrement = 0;
  returnMethod = null;
  
  switch(methodToReturn)
  {
  case WhichMethod.AddOne:
   returnMethod = new Func<Int32>(() => { return integerToIncrement += 1;} );
   break;
  case WhichMethod.AddTwo:
   returnMethod = new Func<Int32>(() => { return integerToIncrement += 2; });
   break;
}
  
 return returnMethod;
}
Let's say we test it like this:
Func<Int32> returnedMethod;
Int32 integerToCheck;

returnedMethod = ReturnIntegerWithinFuncReturningMethod(WhichMethod.AddOne);
integerToCheck = returnedMethod();
Assert.IsTrue(integerToCheck == 1, "Actual value is:" + integerToCheck.ToString());

integerToCheck = returnedMethod();
Assert.IsTrue(integerToCheck == 2, "Actual value is:" + integerToCheck.ToString());
These both pass. How does that make sense? You would think that it would return 1 both times since from first glance integerToIncrement lives outside the actual Func that is returned. You would think from this that Int32 is a reference type. When a value type is "attached" to a Func like this one is, apparently it keeps a reference to it and therefore the original Int32 is updated every time the Func is called. Something to remember.

No comments: