Asp.net Lambda表达式比foreach语句慢?

Asp.net Lambda表达式比foreach语句慢?,asp.net,linq,Asp.net,Linq,我做了一个小实验来测试lamdba表达式是否能比foreach语句更快地检索结果。但是,兰姆达失败了 System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); st.Start(); List<int> lst = new List<int>(); foreach (GridViewRow item in GridView1.Rows)

我做了一个小实验来测试lamdba表达式是否能比foreach语句更快地检索结果。但是,兰姆达失败了

System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
        st.Start();
        List<int> lst = new List<int>();
        foreach (GridViewRow item in GridView1.Rows)
        {
            if (((CheckBox)item.FindControl("Check")).Checked)
            {
                lst.Add(Convert.ToInt32(((Label)item.FindControl("Id")).Text));
            }
        }
        st.Stop();
        Response.Write(st.Elapsed.ToString());
        Response.Write("<br/><br/><br/>");
        st.Reset();
        st.Start();
        List<int> lstRank = GridView1.Rows.OfType<GridViewRow>().Where(s => ((CheckBox)s.FindControl("Check")).Checked)
                                                                     .Select(s => Convert.ToInt32(((Label)s.FindControl("Id")).Text)).ToList();
        st.Stop();
        Response.Write(st.Elapsed.ToString());
        int i = 0;


output
00:00:00.0000249


00:00:00.0002464 
System.Diagnostics.Stopwatch st=新的System.Diagnostics.Stopwatch();
st.Start();
List lst=新列表();
foreach(GridView1.Rows中的GridViewRow项)
{
如果(((复选框)项.FindControl(“检查”)).Checked)
{
lst.Add(Convert.ToInt32(((Label)item.FindControl(“Id”)).Text));
}
}
st.Stop();
Response.Write(st.appeased.ToString());
回答。写(“


”); 圣重置(); st.Start(); List lstRank=GridView1.Rows.OfType()。其中(s=>((复选框)s.FindControl(“检查”)。选中) .Select(s=>Convert.ToInt32(((Label)s.FindControl(“Id”)).Text)).ToList(); st.Stop(); Response.Write(st.appeased.ToString()); int i=0; 输出 00:00:00.0000249 00:00:00.0002464

为什么lambda比foreach慢。这可能是lambda表达式的一个缺点

从技术上讲,您的两种方法并不相同。有一些不同之处,例如使用“
of type
”在继续之前过滤集合。您最好使用“
Cast()
”,因为您知道每个元素都属于GridViewRow类型


另外,您真的需要Linq语句末尾的
ToList()
,因为您的Linq查询现在可以迭代并执行,而不必转换回列表?

lambda表达式的开销很小,因为它们是在运行时“编译”的。我想这就是你在“基准”中看到的。对于每个。。。是一个完全编译的语句


可以预编译lambda表达式。看。也许您想重新编写代码并再次测试。

我不会谈论代码的正确性,但我想有机会解释一下一般规则 在软件开发中,性能损失与消耗水平成反比。 在这种情况下,foreach比LINQ(更抽象)更快是很正常的。 如果您将其与经典for(for(inti:i++l等)进行比较,它将比foreach更快。 访问对象认为接口比访问具体对象慢:接口已经是一个非常小的抽象级别。 您编写的代码将与机器语言“接近”的速度一样快,但当然可读性和可维护性较差。 问题是如何为我们正在开发的东西找到合适的抽象级别,同时关注性能和代码可读性


您不需要使用MVC模式来创建一个在转发器上显示表格的单页网站:-)

您可以在这里查看一下:这里您的基准运行时间不够长,无法真正发挥作用。我不相信测量时间不到几秒钟的基准测试。如果
GridView1.Rows
包含一些不是从
GridViewRow
派生的内容,那么
foreach
版本将抛出类型异常。不,这里不会发生这种情况。这些是普通的lambda,不是表达式树。@Daniel:一个愚蠢的问题和一点OT:普通的lambda完全编译好了吗?找不到说明此内容的链接。你能帮忙吗?对于一个普通的lambda,想象一下编译器只是把你的代码移到一个单独的方法中,然后为它发明一个名称。事实上,您不需要想象:如果使用ILDASM或Reflector查看生成的代码,您可以找到编译器生成的名称。如果lambda从封闭方法捕获(“关闭”)一个局部变量,该变量将成为编译器生成的类的一个字段,该类的一个对象将由外部方法分配,以便可以共享该变量。因此,在运行时不需要进行特殊的解释/编译。@Daniel:非常感谢您的详细和熟练的解释。我很抱歉——就像我问你的那样——这件事没有什么好名声。