如果我有一些foreach循环,例如
foreach (ObjectA a in getAs(param1))
{
foreach (ObjectB b in getBs(param2))
{
//compare a & b
}
}
假设我没有对返回的列表进行任何编辑(它们返回相同的列表),编译器是否足够聪明,只能调用getAs()& getBs()一次,每次?它是否足够聪明,知道它应该将它们转换成字典?
它最终是否会通过LNQ与SQL数据库进行交互,这会产生重大影响(例如,代码可能假设SQL数据库随时都可以更改,但也许它可以检查它是否可以&# 39; s改变了?)
答案 0 :(得分:2)
简短的回答是 否 ,但是长答案更多地与编写代码的方式有关,而不是编译器的效率。
在你的第一个foreach循环中,你获取源一次,并迭代它的元素,有效地只调用一次方法以获得源,但是嵌套的foreach循环被调用一次外循环中的每次迭代,并且由于编译器无法知道嵌套循环中方法的输出是否不会发生变化,因此总是调用方法以获取源是有意义的迭代。
在这种情况下,如果您知道输出将是相同的,那么您需要改进逻辑并避免对方法进行不必要的调用,特别是如果您知道有一些资源消耗操作(例如对数据库的调用)正在进行在那个方法里面。
为了给出详细的答案,我在以下程序中尝试了你的陈述:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace StackOverflow
{
public class Class1
{
public static void Main(string[] args)
{
var serv1 = new Testserv1();
foreach (int x in serv1.CallA())
{
foreach (int y in serv1.CallB())
{
}
}
Console.WriteLine(string.Format("Calls to A: {0}", serv1.ACount));
Console.WriteLine(string.Format("Calls to B: {0}", serv1.BCount));
Console.ReadLine();
}
}
public class Testserv1
{
private static int CallACount = 0;
private static int CallBCount = 0;
public int ACount {
get
{
return CallACount;
}
}
public int BCount
{
get
{
return CallBCount;
}
}
public Testserv1()
{
//InitializeComponent();
}
public List<int> CallA()
{
CallACount++;
return new List<int>() {
1,2,3,4,5,6
};
}
public List<int> CallB()
{
CallBCount++;
return new List<int>() {
7,8,9,10,11,12
};
}
}
}
上一代码的输出是:
Calls to A: 1
Calls to B: 6
答案 1 :(得分:0)
鉴于您的问题中提供的信息,没有正当理由认为编译器会转换为字典。事实上,没有理由使用字典。为什么人们希望编译器从方法调用结果中获取唯一键?
提出的问题并未提供足够的信息,甚至无法回复相关的回复。
必要的细节包括: getAs和getBs方法的返回类型是什么? 比较的基础是什么? 循环期望的用法和结果类型是什么?
每个循环都使用不同的对象,假设在完全缺乏直接信息的情况下编译会以任何方式进行优化,基于什么原因?
给出一个更具体的例子,如:
List<string> intersection = new List<string>();
foreach (string a in GetaList())
{
foreach (string b in GetbList())
{
if (a.Equals(b))
{
intersection.Add(a);
}
}
}
程序集(F11进入步骤,CTRL-F11进行查看程序集)将指示实际为每次迭代调用GetbList,至少在调试模式下。
我相信你的问题的答案是:不,编译器没有为你优化内部方法调用。如果您希望内部方法调用仅发生一次,请在外部循环外进行调用。