gpt4 book ai didi

c# - IEnumerable<> vs List<> 作为参数

转载 作者:行者123 更新时间:2023-12-03 10:04:22 29 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





Performance between Iterating through IEnumerable<T> and List<T>

(5 个回答)



Overhead of implementing an interface

(12 个回答)


去年关闭。




一般来说,我倾向于使用 IEnumerable<>作为我传入参数时的类型。然而,根据 BenchmarkDotNet:

[Benchmark]
public void EnumeratingCollectionsBad()
{
var list = new List<string>();
for (int i = 0; i < 1000; i++)
{
Bad(list);
}
}

[Benchmark]
public void EnumeratingCollectionsFixed()
{
var list = new List<string>();
for (int i = 0; i < 1000; i++)
{
Fixed(list);
}
}

private static void Bad(IEnumerable<string> list)
{
foreach (var item in list)
{
}
}

private static void Fixed(List<string> list)
{
foreach (var item in list)
{
}
}


方法
工作
运行
意思是
错误
标准差
中位数
0代
第一代
第 2 代
已分配


枚举CollectionsBad
.NET 核心 3.1
.NET 核心 3.1
17.802 我们
0.3670 我们
1.0764 我们
17.338 我们
6.3782
-
-
40032乙

枚举CollectionsFixed
.NET 核心 3.1
.NET 核心 3.1
5.015 我们
0.1003 我们
0.2535 我们
4.860 我们
-
-
-
32乙


为什么接口(interface)版本会比具体版本慢得多(并且占用大量内存)?

最佳答案

Why would the interface version be so much slower (and memory intensive) than the concrete version?


当它使用接口(interface)时,迭代必须在堆上分配一个对象......而 List<T>.GetEnumerator() 返回 List<T>.Enumerator ,这是一个结构,不需要任何额外的分配。 List<T>.Enumerator实现 IEnumerator<T> ,但是因为编译器直接知 Prop 体类型,所以不需要装箱。
因此,即使这两种方法都在同一类型的对象( List<T> )上运行,但仍会调用此方法:
IEnumerator<T> GetEnumerator()
...有人称之为:
List<T>.Enumerator GetEnumerator()
第一个几乎可以肯定只是委托(delegate)给第二个,但必须将结果装箱,因为 IEnumerator<T>是引用类型。 List<T>.GetEnumerator() 的事实返回一个可变结构 can have some surprising consequences但它的设计正是为了获得您在此处看到的性能优势。
使用接口(interface)与具体类型本身可能会产生一些非常小的性能损失,但这里的主要原因是分配的差异。

关于c# - IEnumerable<> vs List<> 作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65570281/

29 4 0