char []创建不安全的字符串

时间:2012-01-11 21:00:38

标签: c# string performance unsafe

我正在开发一个高性能代码,其中此构造是性能关键部分的一部分。

这是在某些部分中发生的事情:

  1. “扫描”string,有效存储元数据。
  2. 根据此元数据,主字符串的块被分成char[][]
  3. 应将char[][]转移到string[]
  4. 现在,我知道您只需拨打new string(char[]),但结果必须复制。

    为了避免这个额外的复制步骤发生,我想我必须可以直接写入字符串的内部缓冲区。即使这是一个不安全的操作(我知道这会带来许多影响,如溢出,向前兼容)。

    我已经看到了实现这一目标的几种方法,但没有一种我真的很满意。

    有没有人对如何实现这一点有真正的建议?

    额外信息:
    实际过程不包括必然转换为char[],它实际上是一个“多子串”操作。像3个索引和它们的长度一样。

    StringBuilder对少量的会话有太多的开销。

    修改
    由于我所要求的一些含糊不清的方面,让我重新拟定它。

    这就是:

    1. 主字符串已编入索引。
    2. 主要字符串的部分内容将复制到char[]
    3. char[]转换为string
    4. 我想要做的是合并第2步和第3步,结果是:

      1. 主字符串已编入索引。
      2. 主要字符串的部分内容会被复制到string(并且GC可以在此过程中通过正确使用fixed关键字来保持其权限吗?)。
      3. 请注意,我无法从string []更改输出类型,因为这是一个外部库,项目依赖于它(向后兼容性)。

4 个答案:

答案 0 :(得分:2)

我认为你要做的就是将现有的字符串“原封”成多个较小的字符串而无需为较小的字符串重新分配字符数组。这在托管世界中无效。

出于一个原因,考虑当垃圾收集器到来并在compaction期间收集或移动原始字符串时会发生什么 - 所有其他字符串'内部'现在指向一些任意的其他内存,而不是你把它们雕刻出来的原始字符串。

编辑:与Ben的答案中涉及的字符戳(这很聪明但IMHO有点可怕)形成鲜明对比,你可以分配一个具有预定义容量的StringBuilder,这样就无需重新分配内部数组。请参阅http://msdn.microsoft.com/en-us/library/h1h0a5sy.aspx

答案 1 :(得分:2)

只需创建自己的寻址系统,而不是尝试使用不安全的代码映射到内部数据结构。

string(也可以作为char[]读取)映射到较小字符串数组与构建地址信息列表(索引和每个子字符串的长度)没有区别。因此,请创建一个新的List<Tuple<int,int>>而不是string[],并使用该数据从原始未更改的数据结构中返回正确的字符串。这很容易被封装到暴露string[]的内容中。

答案 2 :(得分:2)

如果您这样做会发生什么:

string s = GetBuffer();
fixed (char* pch = s) {
    pch[0] = 'R';
    pch[1] = 'e';
    pch[2] = 's';
    pch[3] = 'u';
    pch[4] = 'l';
    pch[5] = 't';
}

我认为世界将会结束(或者至少是.NET管理的部分),但这与StringBuilder非常接近。

您是否有分析器数据显示StringBuilder对于您的目的来说不够快,或者这是一个假设?

答案 3 :(得分:0)

在.NET中,无法创建与另一个字符串共享数据的String实例。关于为什么出现的一些讨论出现在Eric Lippert的this comment中。