c# - For vs Foreach -巨大的性能差异

本文关键字:性能 Foreach For vs 巨大 | 更新日期: 2023-09-27 18:02:13

我正在对一个算法进行一些优化,该算法可以在给定数组中找到比X大的最小数字,但是后来我偶然发现了一个奇怪的差异。在下面的代码中,"ForeachUpper"结束于625ms,而"ForUpper"结束于,我相信,几个小时(慢得离谱)。为什么如此?

  class Teste
{
    public double Valor { get; set; }
    public Teste(double d)
    {
        Valor = d;
    }
    public override string ToString()
    {
        return "Teste: " + Valor;
    }
}
  private static IEnumerable<Teste> GetTeste(double total)
    {
        for (int i = 1; i <= total; i++)
        {
            yield return new Teste(i);
        }
    }
    static void Main(string[] args)
    {
        int total = 1000 * 1000*30 ;
        double test = total/2+.7;
        var ieTeste = GetTeste(total).ToList();

        Console.WriteLine("------------");
        ForeachUpper(ieTeste.Select(d=>d.Valor), test);
        Console.WriteLine("------------");
        ForUpper(ieTeste.Select(d => d.Valor), test);
        Console.Read();
    }
    private static void ForUpper(IEnumerable<double> bigList, double find)
    {
        var start1 = DateTime.Now;
        double uppper = 0;
        for (int i = 0; i < bigList.Count(); i++)
        {
            var toMatch = bigList.ElementAt(i);
            if (toMatch >= find)
            {
                uppper = toMatch;
                break;
            }
        }
        var end1 = (DateTime.Now - start1).TotalMilliseconds;
        Console.WriteLine(end1 + " = " + uppper);
    }
    private static void ForeachUpper(IEnumerable<double> bigList, double find)
    {
        var start1 = DateTime.Now;
        double upper = 0;
        foreach (var toMatch in bigList)
        {
            if (toMatch >= find)
            {
                upper = toMatch;
                break;
            }
        }
        var end1 = (DateTime.Now - start1).TotalMilliseconds;
        Console.WriteLine(end1 + " = " + upper);
    }

谢谢

c# - For vs Foreach -巨大的性能差异

IEnumerable<T>不可转位。

for循环的每次迭代中调用的Count()ElementAt()扩展方法是O(n);它们需要循环遍历集合以查找第count或第n个元素。

道德:知道你的集合类型

造成这种差异的原因是您的for循环将在每次迭代时执行bigList.Count()。在您的示例中,这样做的成本非常高,因为它将执行Select并迭代完整的结果集。

此外,您正在使用ElementAt,它再次执行选择并迭代到您提供的索引。