上面這張圖片困檩,是今天波波同學(xué)發(fā)給我的祠挫。剛看到圖片內(nèi)容的瞬間,我不禁一驚悼沿。因?yàn)榈忍颍谖覍懙拇a中Find
和FirstOrDefault
都曾用到,并且在我的概念里兩者幾乎都是等價的糟趾,并沒有本質(zhì)上的區(qū)別慌植。今天看人家還有提供測試數(shù)據(jù),似乎我應(yīng)該將FirstOrDefault
全部都換成Find
才是最優(yōu)的解义郑。
仔細(xì)回想了一下蝶柿,很久之前也曾經(jīng)在StackOverFlow的一個帖子上讀到過,類似的討論非驮。其結(jié)論也是Find
表現(xiàn)出的性能交汤,會大大優(yōu)于FirstOrDefault
。我把原帖搜索出來了:
https://stackoverflow.com/questions/14032709/performance-of-find-vs-firstordefault
發(fā)現(xiàn)這竟然是10多年前的帖子劫笙!拜托芙扎,那時候還是.NET Framework的天下,連.NET Core 1.0都還沒有呢填大!今天已經(jīng)就快步入.NET9的時代戒洼。這個結(jié)論還成立嗎?
既然有所懷疑允华,不如來個實(shí)實(shí)在在的測試圈浇。論證一下,在今天FirstOrDefault
和Find
是否還存在如此大的差距靴寂。
編寫測試代碼
首先磷蜀,創(chuàng)建一個.NET8的控制臺項(xiàng)目。
dotnet new console -o TestListApp
接著榨汤,nuget引入性能測試框架Benchmark.NET
。
dotnet add package BenchmarkDotNet
最后開始寫代碼進(jìn)行測試:
- 新建一個
ListTest.cs
類文件怎茫,然后編寫基準(zhǔn)測試代碼收壕。
[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<ListTest>();
Console.WriteLine(summary);
}
結(jié)果
運(yùn)行基準(zhǔn)測試,幾分鐘后得到結(jié)果如圖:
從結(jié)果來看Find
確實(shí)比FirstOrDefault
執(zhí)行效率略高一些蜜宪,如果代碼里的選擇是用Find
似乎還是比較明智的虫埂。然而,兩個方法之間性能差異數(shù)值并不算很大圃验,大約在3-10%之間掉伏。
因此,我的結(jié)論是能用Find
盡量用Find
澳窑,但如果代碼已經(jīng)用了FirstOrDefault
也不是什么災(zāi)難性的問題斧散,所以不用恐慌,也不必急于馬上改過來摊聋。淡定自若就可以了鸡捐。
最后,我還順帶介紹了BenchmarkDotNet
作為性能測試框架的使用方法麻裁。這也是個一個知識點(diǎn)哦箍镜,希望小伙伴們都能Get到~