推薦一個(gè)開(kāi)源庫(kù),其功能已經(jīng)完全包含LINQ的所有方法,完全可以替代Linq。而且其有更高的性能和低內(nèi)存占用的特點(diǎn)。
?
01
項(xiàng)目簡(jiǎn)介
ZLinq 是一個(gè)由 Cysharp 團(tuán)隊(duì)開(kāi)發(fā)的開(kāi)源項(xiàng)目,目標(biāo)是為所有 .NET 平臺(tái)和 Unity 提供零分配的 LINQ 實(shí)現(xiàn)。它通過(guò)利用 Span 和 SIMD 技術(shù),優(yōu)化了 LINQ 的性能,同時(shí)提供了對(duì)樹(shù)形結(jié)構(gòu)(如文件系統(tǒng)、JSON、游戲?qū)ο蟮龋┑牟樵冎С帧?/span>
通過(guò)一行代碼,調(diào)用AsValueEnumerable() 方法,用戶可以將任何Linq轉(zhuǎn)換為 ZLinq。
using ZLinq;
var seq = source
.AsValueEnumerable() // 添加此代碼
.Where(x => x % 2 == 0)
.Select(x => x * 3);
02
核心特征
零分配 LINQ
傳統(tǒng)的 LINQ 實(shí)現(xiàn)雖然強(qiáng)大,但在處理大量數(shù)據(jù)時(shí)可能會(huì)因?yàn)轭l繁的內(nèi)存分配而導(dǎo)致性能瓶頸。ZLinq 通過(guò)結(jié)構(gòu)體(struct)的方式實(shí)現(xiàn)可枚舉集合,避免了傳統(tǒng) LINQ 中由于頻繁創(chuàng)建對(duì)象而導(dǎo)致的內(nèi)存分配問(wèn)題。
對(duì) Span 的支持
ZLinq 充分利用了 .NET 9/C# 13 中引入的 allows ref struct 特性,支持對(duì) Span 的操作。這意味著用戶可以在支持該特性的環(huán)境中,對(duì) Span 類型進(jìn)行高效的 LINQ 查詢操作。
LINQ to SIMD
ZLinq 自動(dòng)應(yīng)用 SIMD(單指令多數(shù)據(jù))優(yōu)化,以提升性能。用戶可以通過(guò)自定義方式進(jìn)一步優(yōu)化 SIMD 的使用,以滿足特定需求。
LINQ to Tree
ZLinq 擴(kuò)展了 LINQ 的概念,使其能夠應(yīng)用于樹(shù)形結(jié)構(gòu)的查詢。它提供了類似 LINQ to XML 的軸操作(如 Ancestors、Children、Descendants、BeforeSelf 和 AfterSelf),可以對(duì)文件系統(tǒng)、JSON、Unity 的 GameObject 等樹(shù)形結(jié)構(gòu)進(jìn)行查詢。
03
入門指南
1、AsValueEnumerable(),即可使用 ZLinq 的零分配 LINQ。using ZLinq;
var source = new int[] { 1, 2, 3, 4, 5 };
// 調(diào)用 AsValueEnumerable 以應(yīng)用 ZLinq
var seq1 = source.AsValueEnumerable().Where(x => x % 2 == 0);
// 也可以應(yīng)用于 Span(僅在支持 allows ref struct 的 .NET 9/C# 13 環(huán)境中)
Span<int> span = stackalloc int[5] { 1, 2, 3, 4, 5 };
var seq2 = span.AsValueEnumerable().Select(x => x * x);
LINQ to XML 將圍繞軸進(jìn)行查詢的概念引入到了 C# 中。即使你不使用 XML,類似的 API 也被納入了 Roslyn,并有效地用于探索語(yǔ)法樹(shù)。ZLinq 擴(kuò)展了這一概念,使其適用于任何可以被視為樹(shù)形結(jié)構(gòu)的對(duì)象,允許應(yīng)用 Ancestors、Children、Descendants、BeforeSelf 和 AfterSelf。具體來(lái)說(shuō),通過(guò)定義一個(gè)實(shí)現(xiàn)了以下接口的結(jié)構(gòu)體,即可使其可迭代:public interface ITraverser<TTraverser, T> : IDisposable
where TTraverser : struct, ITraverser<TTraverser, T> // 自身
{
T Origin { get; }
TTraverser ConvertToTraverser(T next); // 用于 Descendants
bool TryGetHasChild(out bool hasChild); // 可選:優(yōu)化 Descendants 的使用
bool TryGetChildCount(out int count); // 可選:優(yōu)化 Children 的使用
bool TryGetParent(out T parent); // 用于 Ancestors
bool TryGetNextChild(out T child); // 用于 Children | Descendants
bool TryGetNextSibling(out T next); // 用于 AfterSelf
bool TryGetPreviousSibling(out T previous); // BeforeSelf
}
3、文件系統(tǒng)
//安裝依賴庫(kù)
dotnet add package ZLinq.FileSystem?
using ZLinq;
var root = new DirectoryInfo("C:\\Program Files (x86)\\Steam");
// FileSystemInfo(FileInfo/DirectoryInfo) 可以調(diào)用 `Ancestors`、`Children`、`Descendants`、`BeforeSelf`、`AfterSelf`
var allDlls = root
.Descendants()
.OfType(default(FileInfo)!)
.Where(x => x.Extension == ".dll");
var grouped = allDlls
.GroupBy(x => x.Name)
.Select(x => new { FileName = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count);
foreach (var item in grouped)
{
Console.WriteLine(item);
}
4、JSON(System.Text.Json)
//安裝依賴庫(kù)
dotnet add package ZLinq.Json
using ZLinq;
// System.Text.Json 的 JsonNode 是 LINQ to JSON 的目標(biāo)(不是 JsonDocument/JsonElement)。
var json = JsonNode.Parse("""
{
"nesting": {
"level1": {
"description": "First level of nesting",
"value": 100,
"level2": {
"description": "Second level of nesting",
"flags": [true, false, true],
"level3": {
"description": "Third level of nesting",
"coordinates": {
"x": 10.5,
"y": 20.75,
"z": -5.0
},
"level4": {
"description": "Fourth level of nesting",
"metadata": {
"created": "2025-02-15T14:30:00Z",
"modified": null,
"version": 2.1
},
"level5": {
"description": "Fifth level of nesting",
"settings": {
"enabled": true,
"threshold": 0.85,
"options": ["fast", "accurate", "balanced"],
"config": {
"timeout": 30000,
"retries": 3,
"deepSetting": {
"algorithm": "advanced",
"parameters": [1, 1, 2, 3, 5, 8, 13]
}
}
}
}
}
}
}
}
}
}
""");
// JsonNode
var origin = json!["nesting"]!["level1"]!["level2"]!;
// JsonNode axis, Children, Descendants, Anestors, BeforeSelf, AfterSelf and ***Self.
foreach (var item in origin.Descendants().Select(x => x.Node).OfType<JsoArray>())
{
// [true, false, true], ["fast", "accurate", "balanced"], [1, 1, 2, 3, 5, 8, 13]
Console.WriteLine(item.ToJsonString(JsonSerializerOptions.Web));
}
04
項(xiàng)目地址
https://github.com/Cysharp/ZLinq
該文章在 2025/3/21 12:46:42 編輯過(guò)