.NET 关于 Frozen Collections
系列文章列表,点击展示/隐藏
正文
介绍
.NET 8 引入了 Frozen Collections,这是对已有不可变(Immutable)和只读(ReadOnly)集合的补充。那么,Frozen Collections 有什么独特之处呢?本文将探讨 Frozen Collections 的特点、优势以及适用场景。
Frozen Collections 简介
.NET 8 引入了两种新的抽象类型:FrozenSet<T>
和 FrozenDictionary<TKey, TValue>
。这些类型不能直接实例化,但可以通过扩展方法来创建。
以下是如何创建 Frozen Collections 的示例:
Dictionary<int, string> dictionary = [];
dictionary.Add(1, "One");
dictionary.Add(2, "Two");
FrozenSet<int> frozenNumbers = numbers.ToFrozenSet();
FrozenDictionary<int, string> frozenDict = dictionary.ToFrozenDictionary();
一旦集合被冻结,你就不能修改其值。
Frozen Collections 的优势
Frozen Collections 的关键优势在于它们针对快速查找和枚举进行了优化。然而,创建 Frozen Collections 的成本相对较高。
因此,Frozen Collections 最适合于集合创建不频繁,但在运行时频繁使用的场景。
接下来,我们将通过性能测试来验证这一点。
在继续之前,我想指出 ReadOnly 集合与不可变和 Frozen 集合之间的一个重要区别。
观察以下代码:
FrozenSet<int> frozenNumbers = numbers.ToFrozenSet();
ImmutableList<int> immutableNumbers = numbers.ToImmutableList();
ReadOnlyCollection<int> readOnlyNumbers = numbers.AsReadOnly();
numbers.Add(6);
Console.WriteLine($"Frozen: {string.Join(", ", frozenNumbers)}");
Console.WriteLine($"Immutable: {string.Join(", ", immutableNumbers)}");
Console.WriteLine($"ReadOnly: {string.Join(", ", readOnlyNumbers)}");
// Frozen: 1, 2, 3, 4, 5
// Immutable: 1, 2, 3, 4, 5
// ReadOnly: 1, 2, 3, 4, 5, 6
ReadOnly 集合是现有集合的包装器。你不能修改包装器,但可以修改现有的集合。
性能测试:查找操作
接下来,我们来测试不同集合的查找性能。
我使用了著名的 BenchmarkDotNet 工具。
测试设置如下:
public int CollectionSize { get; set; }
private List<int> _list;
private ImmutableList<int> _immutableList;
private HashSet<int> _hashSet;
private FrozenSet<int> _frozenSet;
[GlobalSetup]
public void SetUp()
{
_list = Enumerable.Range(0, CollectionSize).ToList();
_immutableList = Enumerable.Range(0, CollectionSize).ToImmutableList();
_hashSet = Enumerable.Range(0, CollectionSize).ToHashSet();
_frozenSet = Enumerable.Range(0, CollectionSize).ToFrozenSet();
}
我添加了 HashSet
作为对比。测试的集合大小分别为 100、1000 和 10000 个元素。
测试代码如下:
public void LookupList()
{
for (var i = 0; i < CollectionSize; i++)
_ = _list.Contains(i);
}
[Benchmark]
public void LookupImmutableList()
{
for (var i = 0; i < CollectionSize; i++)
_ = _immutableList.Contains(i);
}
[Benchmark]
public void LookupHashSet()
{
for (var i = 0; i < CollectionSize; i++)
_ = _hashSet.Contains(i);
}
[Benchmark]
public void LookupFrozenSet()
{
for (var i = 0; i < CollectionSize; i++)
_ = _frozenSet.Contains(i);
}
测试结果表明,FrozenSet
的查找性能甚至优于 HashSet
。
性能测试:创建操作
接下来,我们来测试 FrozenSet
的创建成本。
测试代码如下:
{
private readonly int[] Numbers = Enumerable.Range(0, 1000).ToArray();
[Benchmark(Baseline = true)]
public List<int> ToList() => Numbers.ToList();
[Benchmark]
public FrozenSet<int> ToFrozenSet() => Numbers.ToFrozenSet();
[Benchmark]
public HashSet<int> ToHashSet() => Numbers.ToHashSet();
}
测试结果表明,FrozenSet
的创建成本较高。
总结
通过本文的介绍和性能测试,我们了解到 Frozen Collections 是不可变且只读的,针对快速查找和枚举进行了优化。它们最适合于集合创建不频繁,但在运行时频繁使用的场景,例如长期运行的服务。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
2023-02-21 .Net6 + GraphQL + MongoDb拦截器
2022-02-21 关于Code Review
2022-02-21 使用 dotnet watch 时包含 CSHTML 文件
2022-02-21 记一次公司项目缓存击穿
2022-02-21 C# 9 特性二
2022-02-21 C# 9 特性三