
上面這張圖片,是今天波波同學(xué)發(fā)給我的。剛看到圖片內(nèi)容的瞬間,我不禁一驚。因?yàn)?,在我寫的代碼中Find和FirstOrDefault都曾用到,并且在我的概念里兩者幾乎都是等價(jià)的,并沒(méi)有本質(zhì)上的區(qū)別。今天看人家還有提供測(cè)試數(shù)據(jù),似乎我應(yīng)該將FirstOrDefault全部都換成Find才是最優(yōu)的解。
仔細(xì)回想了一下,很久之前也曾經(jīng)在StackOverFlow的一個(gè)帖子上讀到過(guò),類似的討論。其結(jié)論也是Find表現(xiàn)出的性能,會(huì)大大優(yōu)于FirstOrDefault。我把原帖搜索出來(lái)了:
https://stackoverflow.com/questions/14032709/performance-of-find-vs-firstordefault
發(fā)現(xiàn)這竟然是10多年前的帖子!拜托,那時(shí)候還是.NET Framework的天下,連.NET Core 1.0都還沒(méi)有呢!今天已經(jīng)就快步入.NET9的時(shí)代。這個(gè)結(jié)論還成立嗎?
既然有所懷疑,不如來(lái)個(gè)實(shí)實(shí)在在的測(cè)試。論證一下,在今天FirstOrDefault和Find是否還存在如此大的差距。
編寫測(cè)試代碼
首先,創(chuàng)建一個(gè).NET8的控制臺(tái)項(xiàng)目。
dotnet new console -o TestListApp
接著,nuget引入性能測(cè)試框架Benchmark.NET。
dotnet add package BenchmarkDotNet
最后開(kāi)始寫代碼進(jìn)行測(cè)試:
- 新建一個(gè)
ListTest.cs類文件,然后編寫基準(zhǔn)測(cè)試代碼。
[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; }
}
- 打開(kāi)
Program.cs文件,添加以下代碼:
internal class Program
{
var summary = BenchmarkRunner.Run<ListTest>();
Console.WriteLine(summary);
}
結(jié)果
運(yùn)行基準(zhǔn)測(cè)試,幾分鐘后得到結(jié)果如圖:

從結(jié)果來(lái)看Find確實(shí)比FirstOrDefault執(zhí)行效率略高一些,如果代碼里的選擇是用Find似乎還是比較明智的。然而,兩個(gè)方法之間性能差異數(shù)值并不算很大,大約在3-10%之間。
因此,我的結(jié)論是能用Find盡量用Find,但如果代碼已經(jīng)用了FirstOrDefault也不是什么災(zāi)難性的問(wèn)題,所以不用恐慌,也不必急于馬上改過(guò)來(lái)。淡定自若就可以了。
最后,我還順帶介紹了BenchmarkDotNet作為性能測(cè)試框架的使用方法。這也是個(gè)一個(gè)知識(shí)點(diǎn)哦,希望小伙伴們都能Get到~