在.NET Core 2.1中如何使用String.Create的示例 [英] Example of how to use String.Create in .NET Core 2.1

查看:57
本文介绍了在.NET Core 2.1中如何使用String.Create的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人知道如何使用此方法吗?

Does anyone know how this method is intended to be used? The documentation is somewhat 'light'!

public static string Create<TState> (int length, TState state, System.Buffers.SpanAction<char,TState> action);

https://docs.microsoft.com/zh-cn/dotnet/api/system.string.create?view=netcore-2.2

推荐答案

String.Create()方法需要三件事:

The String.Create() method needs three things:


  1. 字符串的最终长度。您必须事先知道这一点,因为该方法需要它安全为用于以下操作的 Span< char> 实例创建内部定长缓冲区构造最终的字符串。

  2. 将成为您字符串的数据(状态)。例如,您可能有一个数组缓冲区(例如,通过网络接收的ascii整数),但是它可能是 anything 。这是原始数据,将转换为最终字符串。在此MSDN文章中有一个示例甚至使用 Random 实例。我还看到了一个不完整的示例,该示例用于创建位图图像(可变大小 state 输入)的base-64编码的哈希值(固定长度),但是可惜我可以做到这一点

  3. action lambda函数将 state 转换为最终字符串的字符。 Create()方法将调用此函数,并传递为字符串和您创建的内部 Span< char> 状态数据作为参数。

  1. The final length of the string. You must know this in advance, because the method needs it to safely create an internal fixed-length buffer for the Span<char> instance used to construct the final string.
  2. The data (state) which will become your string. For example, you might have an array buffer (of, say, ascii integers received over the network), but it could be anything. This is the raw data that will be transformed into the final string. There is an example buried deep in this MSDN article that even uses a Random instance. I've also seen an incomplete example used to create a base-64 encoded hash value (fixed length) of bitmap images (variable sized state input), but sadly I can't find it again.
  3. The action lambda function that transforms state into the characters for the final string. The Create() method will call this function, passing the internal Span<char> it created for the string and your state data as the arguments.

对于一个非常简单的示例,我们可以 Create()由类似这样的字符组成的字符串:

For a very simple example, we can Create() a string from an array of characters like this:

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];
});

当然,基本的 string(char [])构造函数也可以在这里工作,但是可以显示正确的函数。或者我们可以将ascii int 值的数组映射到这样的新字符串:

Of course, the basic string(char[]) constructor would also work here, but that shows what a correct function might look like. Or we can map an array of ascii int values to a new string like this:

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];
});

之所以存在该功能,是因为与传统方法相比,该技术有一些潜在的潜在性能优势。例如,您可以将Stream对象直接传递给 String.Create()(假设您知道最终长度),而不是将Stream读入缓冲区。这样避免了需要分配单独的缓冲区,并且避免了一轮复制值(stream => buffer => string变成stream => string)。

The function exists because there are some significant potential performance wins for this technique over traditional methods. For example, rather than reading a Stream into a buffer, you could pass the Stream object directly to String.Create() (assuming you know the final length). This avoids needing to allocate a separate buffer and avoids one round of copying values (stream=>buffer=>string becomes just stream=>string).

调用 string.Create()时会发生什么,该函数将构造一个新字符串,该字符串的大小已由 length 参数。这是一个(也是唯一一个)堆分配。因为 Create()是字符串类型的成员,所以它可以访问您这个新对象的私有字符串数据,而我通常看不到。现在,它使用此访问权限创建指向新字符串内部字符数据的内部 Span< char> 实例。

What happens when you call string.Create() is the function constructs a new string that already has the size determined by your length argument. This is one (and only one) heap allocation. Because Create() is a member of the string type, it has access to private string data for this new object you and I normally can't see. It now uses this access to create an internal Span<char> instance pointed at the new string's internal character data.

Span< char> 驻留在堆栈上,但是从新字符串作用于堆内存。 。没有额外的分配,并且一旦 Create()函数返回,它就完全超出范围,因此一切合法且安全。而且,因为它基本上是一个有好处的指针,所以除非您做了其他可怕的错误,否则几乎没有溢出堆栈的风险。

This Span<char> lives on the stack, but acts on the heap memory from the new string... there is no additional allocation, and it's completely out of scope as soon as the Create() function returns, so everything is legal and safe. And because it's basically a pointer-with-benefits, there's virtually no risk of overflowing the stack unless you've done something else horribly wrong.

现在 Create()调用您的 action 函数来完成填充字符串的繁重工作。您的操作 lambda可以写入 Span< char> ...,在执行lamdba期间,字符串是

Now Create() calls your action function to do the heavy lifting of populating the string. Your action lambda can write into the Span<char>... for the duration of your lamdba's execution, strings are less-immutable than you may have heard!

动作 lamdba完成时, Create()可以返回新的,随时可用的字符串引用。一切都很好:我们最小化了堆分配,保留了类型安全性和内存安全性; Span< char> 不再可在任何地方访问,并且堆栈值已被破坏。我们还最大限度地减少了缓冲区之间不必要的复制,具体取决于您的 action 实现。

When the action lamdba is finshed, Create() can return the new, ready-to-use, string reference. Everything is good: we minimized heap allocations, preserved type safety and memory safety; the Span<char> is no longer accessible anywhere, and as a stack value is already destroyed. We also minimized unnecessary copying between buffers, depending on your action implementation.

这篇关于在.NET Core 2.1中如何使用String.Create的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆