我需要优化广泛使用linq的大型应用。许多linq语句在linq扩展方法中创建匿名对象。一个例子: -
// custom sort order
var sortedData = data.OrderBy(x => (new List<string>() {"Orange", "Apple", "Pear" }).IndexOf(x.Name));
foreach (var d in sortedData) {
....
问题是每次迭代都会创建一个新的List。
我是否可以设置编译器标志以使编译器进行一些静态分析并将循环不变代码提取到循环之外?
答案 0 :(得分:1)
为什么你不能自己把它拉出来?
var fruits = new [] {"Orange", "Apple", "Pear" };
var sortedData = data.OrderBy(x => fruits.IndexOf(x.Name));
foreach (var d in sortedData) {
此外,如果这些循环都在同一个类中,请使fruits
成为该类的static readonly
成员。
答案 1 :(得分:1)
我认为很多人都是通过榜样赶上你的订单而错过了你真正的问题。
没有没有内置于visual studio的简单工具可以静态执行此操作(无需运行程序)。如果您可以运行程序并执行相关代码,那么有两种工具可以帮助您(您确实拥有100%代码覆盖率的单元测试;))。一个是profiler built in to Visual Studio,另一个是CLR profiler。
我从未使用过CLR分析器,它可能只是visual studio中的旧版本。 visual studio profiler可以显示是否正在创建大量对象(示例中的列表),并查看代码在哪些对象中创建。它还可以显示哪些代码行的执行时间最长,因此您知道在哪里集中精力来加速您的程序。
如果您在运行探查器时遇到特定问题,我建议您就此问题开启一个新问题,
答案 2 :(得分:0)
您可以将LINQ更改为:
// Note the call to ToArray()
var sortedData = data.OrderBy(...).ToArray();
在这种情况下,语句应该执行一次,循环的来源将是常量。
答案 3 :(得分:0)
您无法设置为您自动修复此问题;你必须手动取出匿名对象:
var orderingList = new List<string>() { "Orange", "Apple", "Pear" };
var sortedData = data.OrderBy(x => orderingList.IndexOf(x.Name));
foreach (var d in sortedData) {
...
}
请注意,这不是订购列表的最有效方式,因为您必须遍历data
中每个项目的列表;你最好用字典:
var ordering = new Dictionary<string, int> {
{"Orange", 0}, {"Apple", 1}, {"Pear", 2} };
var sortedData = data.OrderBy(x => ordering.ContainsKey(x) ? ordering[x] : -1);
答案 4 :(得分:-1)
检查FxCop的规则,也许你可以做些什么。