现在是 2019 年,我们有一个使用大型机作为数据存储和交易的银行项目。
我们正在使用 DTO(Commarea,纯 c# 类),它被转换为纯字符串(这是大型机的工作方式),然后发送到大型机。
在将类转换为字符串表示时,我们使用了几种字符串操作,例如子字符串、向左填充、向右填充、修剪等。
可以想象,这会导致多次字符串分配,从而导致垃圾收集。它通常在第 0 代,但仍然如此。
特别是像Decimalwhich is a Pack typein mainframe 这样适合 8 个字节的类型会创建多个字符串。
我尝试使用ReadonlySpan<char>例如子字符串。参见示例。
不过,也有类似的操作PadRight,PadLeft这是不缴费的,因为它是一个只读跨度。
更新: 澄清部分转换发生如下:
val.Trim().Substring(5).PadRight(10);
Run Code Online (Sandbox Code Playgroud)
我知道这会创建 3 个字符串。我知道字符串是不可变的。我的问题是关于使用ReadonlySpanor进行上述操作Memory。
我不能只将 ReadonlySpan 用于子字符串,因为一旦我调用ToString方法,我就会失去好处。
我必须ToString一路打电话到最后。
是否有另一个结构支持子字符串后面的其他操作,我实际上可以将删除数据添加到内存中?
谢谢。
小智 1
使用 ReadOnlySpan 可以帮助减少代码中的字符串分配数量,但并不能完全消除它们。这是因为 ReadOnlySpan 是字符序列的只读视图,因此您无法使用 ReadOnlySpan 修改基础数据。
为了避免不必要的字符串分配,可以使用 string.AsSpan() 方法获取字符串的 ReadOnlySpan 视图,然后使用 Span.Slice() 方法获取子字符串而不分配新字符串。例如,您可以使用以下代码来获取字符串的子字符串,而不分配新字符串:
string val = "Hello world";
ReadOnlySpan<char> span = val.AsSpan();
ReadOnlySpan<char> substring = span.Slice(5);
Run Code Online (Sandbox Code Playgroud)
但是,如前所述,您无法使用 ReadOnlySpan 来修改底层数据,因此您仍然需要为 PadRight 和 PadLeft 等操作分配新的字符串。为了避免这些分配,您可以使用 StringBuilder 逐段构建字符串,然后在完成后在 StringBuilder 上调用 ToString()。这将允许您执行字符串操作,而无需为每个操作分配新字符串。
总之,使用 ReadOnlySpan 可以帮助减少代码中的字符串分配数量,但并不能完全消除它们。为了避免为每个字符串操作分配新的字符串,您可以使用 StringBuilder 逐段构建最终的字符串。
string val = "Hello world";
StringBuilder builder = new StringBuilder(val.Length);
// Trim the string
builder.Append(val.Trim());
// Get a substring starting at the 5th character
builder.Append(val, 5, val.Length - 5);
// Pad the string with spaces to the right, to make it 10 characters long
builder.PadRight(10, ' ');
// Convert the final string to a regular string
string result = builder.ToString();
Run Code Online (Sandbox Code Playgroud)