C# 如何在.NET Core 2.1中使用String.Create的示例
有人知道这个方法是如何使用的吗?文档有点“轻松”C# 如何在.NET Core 2.1中使用String.Create的示例,c#,.net-core,C#,.net Core,有人知道这个方法是如何使用的吗?文档有点“轻松” public static string Create<TState> (int length, TState state, System.Buffers.SpanAction<char,TState> action); 创建公共静态字符串(int-length、TState-state、System.Buffers.SpanAction); 需要三件事: 字符串的最后长度。您必须事先知道这一点,因为该方法需要它为用于
public static string Create<TState> (int length, TState state, System.Buffers.SpanAction<char,TState> action);
创建公共静态字符串(int-length、TState-state、System.Buffers.SpanAction);
需要三件事:
长度
。您必须事先知道这一点,因为该方法需要它为用于构造最终字符串的Span
实例安全地创建一个内部固定长度缓冲区状态
)。例如,您可能有一个数组缓冲区(例如,通过网络接收的ascii整数),但它可以是任何东西。这是将转换为最终字符串的原始数据。有一个深埋其中的例子,它甚至使用了一个Random
实例。我还看到了一个不完整的示例,用于创建位图图像(可变大小state
input)的base-64编码哈希值(固定长度),但遗憾的是,我无法再次找到它操作
lambda函数,用于将状态
转换为最终字符串的字符。Create()
方法将调用此函数,将它为字符串创建的内部Span
和您的状态
数据作为参数传递char[] buffer = {'f', 'o', 'o'};
string result = string.Create(buffer.Length, buffer, (chars, buf) => {
for (int i=0;i<chars.Length;i++) chars[i] = buf[i];
});
int[] buffer = {102, 111, 111};
string result = string.Create(buffer.Length, buffer, (chars, buf) => {
for (int i=0;i<chars.Length;i++) chars[i] = (char)buf[i];
});
该功能的存在是因为与传统方法相比,该技术有一些显著的潜在性能优势。例如,您可以将流对象直接传递给String.Create()
(假设您知道最终长度),而不是将流读入缓冲区。这避免了需要分配单独的缓冲区,并避免了一轮复制值(stream=>buffer=>string变成stream=>string)
调用
string.Create()
时,函数会分配一个新字符串,该字符串的大小已由length
参数确定。这是一个(也是唯一一个)堆分配。因为Create()
是字符串类型的成员,所以它可以访问您和我通常看不到的这个新对象的私有字符串数据。它现在使用此访问创建指向新字符串的内部字符数据的内部Span
实例
这个Span
存在于堆栈上,但作用于来自新字符串的堆内存。。。没有额外的分配,只要Create()
函数返回,它就完全超出了范围,因此一切都是合法和安全的。而且因为它基本上是一个有好处的指针,所以实际上没有溢出堆栈的风险,除非你做了其他可怕的错误
现在Create()
调用您的action
函数来完成填充字符串的繁重工作。您的操作
lambda可以写入Span
。。。在lamdba执行的过程中,字符串的不可更改性比您可能听到的要小
当
操作
lamdba被查找时,Create()
可以返回新的、随时可用的字符串引用。一切都很好:我们最小化了堆分配,保留了类型安全和内存安全;Span
不再可在任何地方访问,因为堆栈值已被销毁。我们还减少了缓冲区之间不必要的复制,这取决于您的操作实现。对字符串进行快速搜索。Create find.Ha!我读了那个文件,完全忘了它在里面。。。谢谢