上面这张图片,是今天波波同学发给我的。刚看到图片内容的瞬间,我不禁一惊。因为,在我写的代码中Find
和FirstOrDefault
都曾用到,并且在我的概念里两者几乎都是等价的,并没有本质上的区别。今天看人家还有提供测试数据,似乎我应该将FirstOrDefault
全部都换成Find
才是最优的解。
仔细回想了一下,很久之前也曾经在StackOverFlow的一个帖子上读到过,类似的讨论。其结论也是Find
表现出的性能,会大大优于FirstOrDefault
。我把原帖搜索出来了:
https://stackoverflow.com/questions/14032709/performance-of-find-vs-firstordefault
发现这竟然是10多年前的帖子!拜托,那时候还是.NET Framework的天下,连.NET Core 1.0都还没有呢!今天已经就快步入.NET9的时代。这个结论还成立吗?
既然有所怀疑,不如来个实实在在的测试。论证一下,在今天FirstOrDefault
和Find
是否还存在如此大的差距。
编写测试代码
首先,创建一个.NET8的控制台项目。
dotnet new console -o TestListApp
接着,nuget引入性能测试框架Benchmark.NET
。
dotnet add package BenchmarkDotNet
最后开始写代码进行测试:
新建一个
ListTest.cs
类文件,然后编写基准测试代码。 ``` [MemoryDiagnoser] public class ListTest { [Benchmark] public int? TestFindInt() {var list = new List<int>(5000); for (int i = 0; i < 5000; i++) { list.Add(i); } return list.Find(i => i > 1200);
}
[Benchmark] public int? TestFirstInt() {
var list = new List<int>(5000); for (int i = 0; i < 5000; i++) { list.Add(i); } return list.FirstOrDefault(i => i > 1200);
}
[Benchmark] public object? TestFindObject() {
var list = new List<Student>(5000); for (int i = 0; i < 5000; i++) { list.Add(new Student() { Id = i + 1, Name = "Student" + i, Age = i % 4 + 18 }); } return list.Find(o => o.Id == 339);
}
[Benchmark] public object? TestFirstObject() {
var list = new List<Student>(5000); for (int i = 0; i < 5000; i++) { list.Add(new Student() { Id = i+1, Name="Student"+i, Age = i%4 + 18 }); } return list.FirstOrDefault(o => o.Id==339);
} }
class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
- 打开 `Program.cs` 文件,添加以下代码:
internal class Program
{
var summary = BenchmarkRunner.Run
Console.WriteLine(summary);
}
```
结果
运行基准测试,几分钟后得到结果如图:
从结果来看Find
确实比FirstOrDefault
执行效率略高一些,如果代码里的选择是用Find
似乎还是比较明智的。然而,两个方法之间性能差异数值并不算很大,大约在3-10%之间。
因此,我的结论是能用Find
尽量用Find
,但如果代码已经用了FirstOrDefault
也不是什么灾难性的问题,所以不用恐慌,也不必急于马上改过来。淡定自若就可以了。
最后,我还顺带介绍了BenchmarkDotNet
作为性能测试框架的使用方法。这也是个一个知识点哦,希望小伙伴们都能Get到~