【发布时间】:2012-03-26 14:37:14
【问题描述】:
我很好奇编译器如何处理循环中声明的 lambda。在一些情况下,我已将 lambda 声明为内联,以便可以在 lambda 中使用调用方法的本地变量。我在下面包含了两个示例。
编译器会在循环中为 lambda 创建 N 个委托吗?在这种情况下,编译器可以进行哪些(以及哪些)优化?此外,MSDN mentions to use lambdas over anonymous functions,但没有深入说明原因。所以为什么?
示例 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";
}
}
示例 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);
}
}
似乎我在示例 1 中完成的并不多。使用 lambda 更容易编写,因为我不必进行任何转换。但是,我想传递给委托的任何方法局部变量都可以通过object state 参数来实现。
在示例 2 中,使用方法局部变量似乎更简洁,而不是设置静态变量,特别是因为静态变量实现似乎不是线程安全的。
我正在寻找关于 lambda 函数的最佳使用以及在上述每个示例中哪些案例得到最佳优化的答案。
【问题讨论】: