在.Net 7 ImmutableArray開始支援Span

前言

Span/ReadOnlySpan自從。Net Core 2。1面世後,在BCL基礎庫使用的地方越來越多,前一段時間在更新Runtime原始碼,發現在ImmutableArray中也開始支援Span了。如果對Span不熟悉的話,可以看看: 在。Net Core中使用Span

在.Net 7 ImmutableArray開始支援Span

快速上手(示例程式碼)

Action> printAction = static (ImmutableArray arr) => { foreach (var item in arr) { Console。Write($“{item} ”); } Console。WriteLine(); }; int[] arr1 = { 1, 2, 3 }; Span span1 = arr1。AsSpan(); //Create 接受Span型別引數 ImmutableArray immutableArray1 = ImmutableArray。Create(span1); printAction(immutableArray1); int[] arr2 = new int[] { 4, 5, 6 }; Span span2 = arr2。AsSpan(); //InsertRange指定下標,將span加入ImmutableArray中 ImmutableArray immutableArray2 = immutableArray1。InsertRange(immutableArray1。Length, span2); printAction(immutableArray2); //Span返回ImmutableArray ImmutableArray immutableArray3 = span2。ToImmutableArray(); printAction(immutableArray3); //Slice切片取第一個元素 ImmutableArray immutableArray4 = immutableArray3。Slice(0, 1); printAction(immutableArray4); int[] arr3 = new int[] { 7, 8, 9 }; //將Span新增到ImmutableArray ImmutableArray immutableArray5 = immutableArray3。AddRange(new ReadOnlySpan(arr3)); printAction(immutableArray5); int[] arr4 = new int[3]; //從ImmutableArray的資料複製到陣列中 ImmutableArray。Create(1, 2, 3)。ToBuilder()。CopyTo(arr4);

ImmutableArray原始碼實現

ImmutableArray原始碼路徑:src/libraries/System。Collections。Immutable/src/System/Collections/Immutable/

檔案主要有:

ImmutableArray

cs

/

ImmutableArray_1。Builder

cs

/

ImmutableArray_1

cs

/

ImmutableArray_1。netcoreapp

cs

public static ImmutableArray Create(ReadOnlySpan items){ if (items。IsEmpty) { return ImmutableArray。Empty; } T[] array = items。ToArray(); return new ImmutableArray(array);}public static ImmutableArray Create(Span items){ return Create((ReadOnlySpan)items);}public static ImmutableArray ToImmutableArray(this ReadOnlySpan items){ return Create(items);}public static ImmutableArray ToImmutableArray(this Span items){ return Create((ReadOnlySpan)items);}public void AddRange(ReadOnlySpan items){ int offset = this。Count; this。Count += items。Length; items。CopyTo(new Span(_elements, offset, items。Length));}public void AddRange(ReadOnlySpan items) where TDerived : T{ int offset = this。Count; this。Count += items。Length; var elements = new Span(_elements, offset, items。Length); for (int i = 0; i < items。Length; i++) { elements[i] = items[i]; }}public void CopyTo(Span destination){ Requires。Range(this。Count <= destination。Length, nameof(destination)); new ReadOnlySpan(_elements, 0, this。Count)。CopyTo(destination);}public ImmutableArray AddRange(ReadOnlySpan items){ var self = this; return self。InsertRange(self。Length, items);}public ImmutableArray AddRange(params T[] items){ var self = this; return self。InsertRange(self。Length, items);}public ReadOnlySpan AsSpan(int start, int length) => new ReadOnlySpan(array, start, length);public void CopyTo(Span destination){ var self = this; self。ThrowNullRefIfNotInitialized(); Requires。Range(self。Length <= destination。Length, nameof(destination)); self。AsSpan()。CopyTo(destination);}public ImmutableArray InsertRange(int index, T[] items){ var self = this; self。ThrowNullRefIfNotInitialized(); Requires。Range(index >= 0 && index <= self。Length, nameof(index)); Requires。NotNull(items, nameof(items)); if (items。Length == 0) { return self; } if (self。IsEmpty) { return new ImmutableArray(items); } return self。InsertSpanRangeInternal(index, items);}public ImmutableArray InsertRange(int index, ReadOnlySpan items){ var self = this; self。ThrowNullRefIfNotInitialized(); Requires。Range(index >= 0 && index <= self。Length, nameof(index)); if (items。IsEmpty) { return self; } if (self。IsEmpty) { return items。ToImmutableArray(); } return self。InsertSpanRangeInternal(index, items);}public ImmutableArray RemoveRange(ReadOnlySpan items, IEqualityComparer? equalityComparer = null){ var self = this; self。ThrowNullRefIfNotInitialized(); if (items。IsEmpty || self。IsEmpty) { return self; } if (items。Length == 1) { return self。Remove(items[0], equalityComparer); } var indicesToRemove = new SortedSet(); foreach (T item in items) { int index = -1; do { index = self。IndexOf(item, index + 1, equalityComparer); } while (index >= 0 && !indicesToRemove。Add(index) && index < self。Length - 1); } return self。RemoveAtRange(indicesToRemove);}public ImmutableArray RemoveRange(T[] items, IEqualityComparer? equalityComparer = null){ var self = this; self。ThrowNullRefIfNotInitialized(); Requires。NotNull(items, nameof(items)); return self。RemoveRange(new ReadOnlySpan(items), equalityComparer);}public ImmutableArray Slice(int start, int length){ var self = this; self。ThrowNullRefIfNotInitialized(); return ImmutableArray。Create(self, start, length);}private ImmutableArray InsertSpanRangeInternal(int index, ReadOnlySpan items){ Debug。Assert(array != null); Debug。Assert(!IsEmpty); Debug。Assert(!items。IsEmpty); var tmp = new T[Length + items。Length]; if (index != 0) { Array。Copy(array!, tmp, index); } items。CopyTo(new Span(tmp, index, items。Length)); if (index != Length) { Array。Copy(array!, index, tmp, index + items。Length, Length - index); } return new ImmutableArray(tmp);}

ImmutableArray新增的原始碼還是很易讀的,就沒有加註釋。

個人能力有限,如果您發現有什麼不對,請私信我

如果您覺得對您有用的話,可以點個贊或者加個關注,歡迎大家一起進行技術交流