3

这可能吗?鉴于 C# 使用不可变字符串,可以预期会有一种方法如下:

var expensive = ReadHugeStringFromAFile();
var cheap = expensive.SharedSubstring(1);

如果没有这样的功能,为什么还要让字符串不可变呢?或者,如果字符串由于其他原因已经是不可变的,为什么不提供这种方法呢?

我正在调查的具体原因是进行一些文件解析。简单的递归下降解析器(例如由 TinyPG 生成的解析器,或易于手工编写的解析器)到处都使用 Substring。这意味着如果你给他们一个大文件来解析,内存流失是难以置信的。当然有变通办法——基本上是滚动您自己的 SubString 类,然后当然忘记能够使用诸如 StartsWith 之类的 String 方法或诸如 Regex 之类的 String 库,因此您也需要滚动您自己的版本。我假设像 ANTLR 这样的解析器生成器基本上可以做到这一点,但我的格式很简单,无法证明使用这种怪物工具是合理的。即使是 TinyPG 也可能是矫枉过正。

有人请告诉我,我在某处遗漏了一些明显或不那么明显的标准 C# 方法调用......

4

6 回答 6

5

不,没有那样的。

.NET 字符串直接包含它们的文本数据,这与 Java 字符串不同,Java 字符串具有对 char 数组、偏移量和长度的引用。

两种解决方案在某些情况下都有“胜利”,而在其他情况下则有损失。

如果您绝对确定这将成为您的杀手锏,您可以实现一个 Java 风格的字符串以在您自己的内部 API 中使用。

于 2009-06-16T21:10:37.100 回答
2

据我所知,所有较大的解析器都使用流进行解析。不适合你的情况吗?

于 2009-06-16T21:13:00.230 回答
1

.NET 框架支持字符串实习。这是一个部分解决方案,但不提供重用字符串部分的可能性。我认为重用子字符串会导致一些乍一看并不明显的问题。如果您必须使用StringBuilder进行大量字符串操作,那么您可以这样做。

于 2009-06-16T21:11:02.793 回答
0

C# 中没有任何东西可以为您提供您正在寻找的开箱即用的功能。

想要的是一个绳索数据结构,一个不可变的数据结构,它支持 O(1) 连接和 O(log n) 子串。我找不到绳索的任何 C# 实现,但这里是 Java 的

除此之外,如果使用 TinyPG 或 ANTLR 是完成工作的最简单方法,那也没有任何问题。

于 2009-06-16T21:15:49.087 回答
0

好吧,您可以使用“不安全”来自己进行内存管理,这可能使您可以做您正在寻找的事情。此外,StringBuilder 类非常适合需要多次操作字符串的情况,因为它不会在每次操作时创建一个新字符串。

于 2009-06-16T21:15:51.863 回答
0

您可以轻松编写一个简单的类来表示“便宜”。它只保存子字符串开头的索引和子字符串的长度。有几种方法可以让您在需要时读取子字符串 - 字符串转换运算符将是您可以使用的理想选择

string text = myCheapObject;

它可以无缝地工作,就好像它是一个实际的字符串一样。添加对 StartsWith 等一些方便的方法的支持将是快速和容易的(它们都是一个衬垫)。

另一种选择是编写一个常规解析器并将您的标记存储在字典中,您可以从中共享对标记的引用,而不是保留多个副本。

于 2009-06-16T21:16:38.927 回答