【问题标题】:Substring Without any Allocation Using Span<T>使用 Span<T> 没有任何分配的子字符串
【发布时间】:2019-04-14 16:48:47
【问题描述】:

我们如何使用Span&lt;T&gt; 而不是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?

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

我知道一个新的构造函数已添加到接受ReadOnlySpan&lt;T&gt; 的 String 类中,例如:

var firstName = new string(span);

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

【问题讨论】:

  • 使用new string(…),您将获得全新的string 对象,该对象必须分配到某个地方。并且由于它可以比当前方法寿命更长,因此不能在堆栈上分配。
  • @PetSerAl Span&lt;T&gt; 位于堆栈上,但其内容可能位于堆上。因此,通过使用new string(span),我们正在创建一个可以指向堆中某处的指针。
  • 您的问题是——分配给firstNamenew string 是在堆上分配的吗?如果是这样,答案是肯定的——字符串总是在堆上分配的。我的后续问题是 - 你为什么在乎?你的根本问题是什么?这感觉像是一个 XY 问题 - meta.stackexchange.com/questions/66377/what-is-the-xy-problem或者您是在问span(这完全是一个不同的问题)?
  • 简单测试,var firstName = new string(span)修改span后告诉我们你创建的字符串发生了什么,你会回答你的问题
  • 不,你不能那样做。

标签: c# string performance memory substring


【解决方案1】:

如您所知,System.String is immutable。没有但是,没有如果。如果您有一个Span&lt;char&gt; 并希望将它们视为string,则会分配新的内存。

好消息是,随着Span&lt;&gt; 的引入,除了接受字符串和数组之外,框架中的许多内置方法都已更新为接受它。引用this MSDN article(我添加了一些示例的链接):

.. 框架中添加了许多这样的方法。从System.RandomSystem.Text.StringBuilder 再到System.Net.Sockets,添加了重载以使{ReadOnly}Span&lt;T&gt;{ReadOnly}Memory&lt;T&gt; 的工作变得简单高效。

这还包括所有数字 {Try}Parse(string) 方法,它们现在将具有对应的 (ReadOnlySpan&lt;char&gt;) overloads

var str = "123,456";
var span = str.AsSpan(0,3);
var i = int.Parse(span);

因此,与其从您的跨度中获取string,不如看看您想要实现的目标是否可以直接利用Span&lt;&gt;

【讨论】:

    猜你喜欢
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    相关资源
    最近更新 更多