I was curious in what ways the compiler handled lambdas declared in loops. I've had a few cases where I've declared lambdas inline so that I can use variables local to the calling method within the lambda. I've included two examples below.
Will the compiler create N delegates for a lambda within a loop? What (and which) optimizations can the compiler make in such cases? Additionally, MSDN mentions to use lambdas over anonymous functions, but doesn't go into depth as to why. So, why?
Example 1:
public static class MethodPlayground1
{
public static void TestMethod()
{
for (int i = 1; i <= 12; i++)
{
int methodLocal1 = i;
string methodLocal2 = i.ToString();
KeyValuePair<int, string> methodLocal3 = new KeyValuePair<int, string>(i, i.ToString());
// Case A
ThreadPool.QueueUserWorkItem((state) =>
{
int threadLocal1 = methodLocal1 + 1;
string threadLocal2 = methodLocal2 + " o'clock";
int threadLocal3 = methodLocal3.Key + 2;
string threadLocal4 = methodLocal3.Value + " oranges";
});
// Case B
ThreadPool.QueueUserWorkItem(delegate(object state)
{
int threadLocal1 = methodLocal1 + 1;
string threadLocal2 = methodLocal2 + " o'clock";
int threadLocal3 = methodLocal3.Key + 2;
string threadLocal4 = methodLocal3.Value + " oranges";
});
// Case C
ThreadPool.QueueUserWorkItem((state) =>
{
int threadLocal1 = methodLocal1 + 1;
string threadLocal2 = methodLocal2 + " o'clock";
int threadLocal3 = methodLocal3.Key + 2;
string threadLocal4 = methodLocal3.Value + " oranges";
});
// Case D
ThreadPool.QueueUserWorkItem(delegate(object state)
{
int threadLocal1 = methodLocal1 + 1;
string threadLocal2 = methodLocal2 + " o'clock";
int threadLocal3 = methodLocal3.Key + 2;
string threadLocal4 = methodLocal3.Value + " oranges";
});
// Case E
ThreadPool.QueueUserWorkItem(AsyncMethod, new object[] { methodLocal1, methodLocal2, methodLocal3 });
}
}
private static void AsyncMethod(object state)
{
object[] methodArgs = (object[])state;
int methodArg1 = (int)methodArgs[0];
string methodArg2 = (string)methodArgs[1];
KeyValuePair<int, string> methodArg3 = (KeyValuePair<int, string>)methodArgs[2];
int threadLocal1 = methodArg1 + 1;
string threadLocal2 = methodArg2 + " o'clock";
int threadLocal3 = methodArg3.Key + 2;
string threadLocal4 = methodArg3.Value + " oranges";
}
}
Example 2:
public static class MethodPlayground2
{
private static int PriorityNumber;
public static void TestMethod()
{
List<int> testList = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7 });
for (int i = 1; i <= 7; i++)
{
// Case A
testList.Sort((i1, i2) =>
{
if ((i1 == i) || (i2 == i))
{
if (i1 == i2) return 0;
else if (i1 == i) return -1;
else return 1;
}
else return i1.CompareTo(i2);
});
// Case B
testList.Sort(delegate(int i1, int i2)
{
if ((i1 == i) || (i2 == i))
{
if (i1 == i2) return 0;
else if (i1 == i) return -1;
else return 1;
}
else return i1.CompareTo(i2);
});
PriorityNumber = i;
// Case C
testList.Sort(IntCompareWithPriority1);
// Case D
testList.Sort(IntCompareWithPriority2);
// Case E
testList.Sort(IntCompareWithPriority3);
}
}
private static Comparison<int> IntCompareWithPriority1 = (i1, i2) =>
{
if ((i1 == PriorityNumber) || (i2 == PriorityNumber))
{
if (i1 == i2) return 0;
else if (i1 == PriorityNumber) return -1;
else return 1;
}
else return i1.CompareTo(i2);
};
private static Comparison<int> IntCompareWithPriority2 = delegate(int i1, int i2)
{
if ((i1 == PriorityNumber) || (i2 == PriorityNumber))
{
if (i1 == i2) return 0;
else if (i1 == PriorityNumber) return -1;
else return 1;
}
else return i1.CompareTo(i2);
};
private static int IntCompareWithPriority3(int i1, int i2)
{
if ((i1 == PriorityNumber) || (i2 == PriorityNumber))
{
if (i1 == i2) return 0;
else if (i1 == PriorityNumber) return -1;
else return 1;
}
else return i1.CompareTo(i2);
}
}
It seems that I'm not accomplishing much in Example 1. Using lambdas is a little easier to write, since I don't have to do any casting. However, any of the method local variables that I want to pass into the delegate I can do so through the object state parameter.
In Example 2, it seems much cleaner to use the method local variables, as opposed to setting a static variable, especially since the static variable implementation doesn't seem it would be thread-safe.
I'm looking for an answer as to the best use of lambda functions and which of the Cases are best optimized in each of the Examples above.