哪个更快?循环遍历对象属性还是使用linq查询?

3

这个更快吗?

var query = from prop in object.GetType().GetProperties()
            where prop.Name == "Id"
            select prop;

var singleProperty = query.SingleOrDefault();
//do stuff with singleProperty

比这更好吗?
var type = object.GetType();
foreach(var prop in type.GetProperties())
{
  if(prop.Name == "Id")
   {
     //do stuff
   }
}

另一种方式?还是它们是相同的?为什么以及如何知道呢?
抱歉问题直接了点。我更喜欢第一种,但我不知道为什么或者是否应该这样做。
谢谢。
3个回答

4
从技术上讲,第一种情况可能会分配更多的内存并进行更多的处理来生成最终结果,因为存在中间数据和LINQ抽象。但在整个过程中,所需的时间和内存量是如此微不足道,因此对于这种情况,使您的代码最易读而不是最有效率是更好的选择。这可能是过早优化的一种情况。
以下是一些参考资料,解释为什么第一种情况可能稍慢:
  1. http://www.schnieds.com/2009/03/linq-vs-foreach-vs-for-loop-performance.html
  2. http://ox.no/posts/linq-vs-loop-a-performance-test
  3. http://geekswithblogs.net/BlackRabbitCoder/archive/2010/04/23/c-linq-vs-foreach---round-1.aspx

但是如果您不评估整个IEnumerable,它可能会处理较少的数据... .ToList()就是这样做的。 - dwerner
有道理。我很好奇是否还有其他观点。感谢您的意见,mellamokb。 - trevorc
@Daniel。如果不进行评估,你将如何访问属性的名称和值? - trevorc
2
如果你只需要返回第一个属性,可以使用First()。类似于在prop.Name=="id"时,在foreach循环中使用break语句。生成器的想法是备份IEnumerable,并且您不需要对所有元素进行求值才能获取它们的子集。 - dwerner
@Daniel +1。我在使用SingleOrDefault()和ToList()时变得有些懒惰了。 - trevorc

1

正确的答案是:使用反射器查看编译器生成了什么。

话虽如此,您的LINQ查询正在使用与其他代码片段相同的机制来检索属性列表。从技术上讲,它应该比涉及LINQ开销的方式更快。但是,我预计差异将是微不足道的(即无法察觉的),因此这实际上取决于代码可读性和可维护性的决定。

而且我讨厌LINQ,所以跳过它。

一年后的回顾:

我发现LINQ并不像我想象的那样可怕。我对其实现感到非常印象深刻,并花了很多时间查看IL,试图找到一个合理的理由不喜欢它。 话虽如此:LINQ-to-objects非常流畅。然而,未来的项目中如果涉及数据库,请不要使用它作为在客户端执行所有查询而不是让数据库服务器做它非常擅长的事情的理由。


1
因为在 C# 源代码中混杂 SQL 查询语句感觉像是糟糕的编码。 - 3Dave
1
我想我对于用一堆结构相同的for/foreach循环来处理数据集合的代码感到不满。正如@Reddog所说,各有所好 :-) - mellamokb
1
@David Lively,那是主观的、争论性的和激烈的。这与主题无关。此外,请查看我的帖子以及MEMark的帖子,并告诉我它是否不会使它更加清晰... https://dev59.com/UFnUa4cB1Zd3GeqPWgSJ#6616972 - Filip Ekberg
@David。你的跟进让我微笑,因为我讨厌尝试查看foreach括号。我想这只是个人偏好。谢谢。 - trevorc
1
@Filip 火爆?我回答了问题并提供了个人观点,说明了特定技术的价值。这很难算是火爆行为。 - 3Dave

0

它们在性能方面是相同的,因为LINQ利用了deferred execution。然而,使用LINQ选项可能会导致略微(且无关紧要)更多的内存。

因此,它们在性能和行为上是(实际上)相同的!

我会选择LINQ版本以提高可读性,因为我喜欢LINQ,但每个人都有自己的选择。


不想挑毛病,但如果一个解决方案需要更多的内存,它们就不能拥有相同的性能。分配/释放内存,垃圾回收等都需要时间。 - 3Dave
还有一个事实,foreach使用一个类来进行操作以便迭代数组。每次调用该迭代器类都会因为使用指针和调用函数而产生性能损失。通常情况下,普通的for循环是最快的。但如果涉及到排序,linq有一些巧妙的技巧可以使其更快。 - TamusJRoyce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接