var
str
=
"123456"
;
var
array
=
str
.
ToCharArray
();
Console
.
WriteLine
(
array
);
var
span
=
new
Span
<
char
>(
array
);
AddOne
(
span
);
Console
.
WriteLine
(
array
);
private
static
void
AddOne
(
Span
<
char
>
span
)
for
(
var
index
=
0
;
index
<
span
.
Length
;
index
++)
var
slice
=
span
.
Slice
(
index
,
1
);
var
value
=
(
byte
)
span
[
index
]+
1
;
slice
.
Fill
((
char
)
value
);
这里是将一个字符串的每一位数字加1
结果如图所示。
这个并没有体现span优势,但是如果我们现在期望只对原始字符串的某些子串进行处理呢?
很多人会想到使用substring,但是substring会返回一个新的字符串,这里就会增加内存开销。
那么使用数组如何?新建一个数组然后拷贝值过去,仍然是增加内存开销。
基于原数组处理呢?那就需要对AddOne方法添加重载,传入起始位置和长度。
那么span怎么做呢?如下图所示,使用slice切片即可
static void Main(string[] args)
var str = "123456";
var array = str.ToCharArray();
Console.WriteLine(array);
var span = new Span<char>(array);
//传入一个slice即可
AddOne(span.Slice(2,2));
Console.WriteLine(array);
换言之Span的高效,不仅在于其只是一段连续内存的”视图”,而且,对于所有的处理方法可以和子集的处理方法统一API接口。(这里你可以类比下指针的功能,而span相对于指针的优势在于不需要length,而且内存可以GC)
这里对连续的内存对象的密集型操作是一个极大的优势
同JavaScript的ArrayBuffer比较
JavaScript中的ArrayBuffer和Span很相似,也是提供对一段内存处理的接口。阮一峰在ArrayBuffer - ECMAScript 6入门介绍他的来源是应用WebGL处理浏览器与显卡之间大量二进制数据的高效实时传输。
因此,我们可以推测,3D渲染,绘图,以及嵌入式开发等一些对效率和内存使用敏感的场景也都会是Span的用武之地
参考文档:
[Span Struct (System) - Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=netcore-3.1)
C# - All About Span: Exploring a New .NET Mainstay - Microsoft Docs
[C# 7 Series, Part 10: Span and universal memory management – Mark Zhou's Tech Blog](https://blogs.msdn.microsoft.com/mazhou/2018/03/25/c-7-series-part-10-spant-and-universal-memory-management/)
ArrayBuffer - ECMAScript 6入门
本文会经常更新,请阅读原文:
https://xinyuehtx.github.io/post/C-%E7%9A%84span%E5%85%83%E7%B4%A0%E7%9A%84%E4%BC%98%E5%8A%BF%E5%9C%BA%E6%99%AF%E5%9C%A8%E5%93%AA%E9%87%8C.html
,以避免陈旧错误知识的误导,同时有更好的阅读体验。
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接:
https://xinyuehtx.github.io
),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请