使用 Span<T> 没有任何分配的子字符串

Ehs*_*edi 5 c# memory string performance substring

我们如何使用Span<T>代替string.Substring来消除堆分配的必要性?假设我们有以下代码:

var firstNameAndFamilyName="myname,myfamily";
var span = firstNameAndFamilyName.AsSpan().Slice(0,6);
var firstName = .... //  How can I get 'myname' without allocating any new memory on the heap?
Run Code Online (Sandbox Code Playgroud)

请注意,我知道该字符串"myname,myfamily"位于堆上并且firstName需要指向堆中的某处。我的问题是,我们如何才能指向字符串的子集而不将该部分处理到堆内存的新位置?

我知道一个新的构造函数已添加到 String 类,它接受ReadOnlySpan<T>如下:

var firstName = new string(span);
Run Code Online (Sandbox Code Playgroud)

但是我找不到任何地方是否通过在堆上分配来完成。

NPr*_*ras 7

如您所知,System.String 是不可变的。没有但是,没有如果。如果您有 aSpan<char>并希望将它们视为string,则将分配新内存。

好消息是,引进的Span<>很多内置的框架方法已经更新的接受它,除了接受字符串和数组。引用这篇 MSDN 文章(我添加了一些示例的链接):

.. 跨框架添加了许多这样的方法。从System.RandomSystem.Text.StringBuilderSystem.Net.Sockets,已添加的过载,使有工作{ReadOnly}Span<T>{ReadOnly}Memory<T>简单高效。

这还包括{Try}Parse(string)现在将具有相应(ReadOnlySpan<char>) 重载的所有数字方法。

var str = "123,456";
var span = str.AsSpan(0,3);
var i = int.Parse(span);
Run Code Online (Sandbox Code Playgroud)

因此,与其string从您的跨度中获取 a ,不如看看您要实现的目标是否可以Span<>直接利用。