C# 如何创建内存<;T>;从一个跨度<;T>;?
我正在尝试重载解析方法,以便在C# 如何创建内存<;T>;从一个跨度<;T>;?,c#,.net,.net-core,C#,.net,.net Core,我正在尝试重载解析方法,以便在字符串版本之外使用ReadOnlySpan参数。问题在于,实现使用字典作为解析逻辑 我尝试将它切换到字典,但当然,它不能作为ReadOnlySpan作为泛型参数,因为它是一个仅用于堆栈的对象。然后我切换到使用允许的ReadOnlyMemory。然后我实现了一个基本的Ordinal比较器,但是现在从ReadOnlySpan参数创建ReadOnlyMemory时遇到了问题。这可能吗 更新 这似乎是不可能的。为了支持我在上面发布的场景,我将更改字典,使其具有int键,这是
字符串
版本之外使用ReadOnlySpan
参数。问题在于,实现使用字典
作为解析逻辑
我尝试将它切换到字典
,但当然,它不能作为ReadOnlySpan
作为泛型参数,因为它是一个仅用于堆栈的对象。然后我切换到使用允许的ReadOnlyMemory
。然后我实现了一个基本的Ordinal
比较器,但是现在从ReadOnlySpan
参数创建ReadOnlyMemory
时遇到了问题。这可能吗
更新
这似乎是不可能的。为了支持我在上面发布的场景,我将更改字典,使其具有int键,这是
ReadOnlySpan
的hashcode,并将该值作为一个包含嵌入元素的字符串的列表,手动解决hash代码冲突。最近有一篇文章介绍了Span
Span
实例只能位于堆栈上,而不能位于堆上这意味着您不能装箱Span(因此不能将Span
与现有的反射调用API一起使用,例如,因为它们需要装箱)。这意味着类中甚至非ref-like结构中都不能有Span
字段。这意味着您不能在Span可能隐式成为类上的字段的位置使用Span,例如通过将它们捕获到lambda中,或作为异步方法或迭代器中的局部变量(因为这些“局部变量”可能最终成为编译器生成的状态机上的字段)。这还意味着您不能将Span
用作泛型参数,作为该类型参数的实例,它可能最终被装箱或以其他方式存储到堆中(并且当前没有可用的“where T:ref struct
”约束)
您可以从数组中创建内存
,并按自己的方式对其进行切片
将是一个跨度,但它是一个(非ref-like)结构,可以在
堆然后,当您想要进行同步处理时,您可以得到
Span
,例如:
static async Task<int> ChecksumReadAsync(Memory<byte> buffer, Stream stream)
{
int bytesRead = await stream.ReadAsync(buffer);
return Checksum(buffer.Span.Slice(0, bytesRead));
// Or buffer.Slice(0, bytesRead).Span
}
static int Checksum(Span<byte> buffer) { ... }
静态异步任务ChecksumReadAsync(内存缓冲区、流)
{
int bytesRead=wait stream.ReadAsync(缓冲区);
返回校验和(buffer.Span.Slice(0,bytesRead));
//或buffer.Slice(0,字节读取).Span
}
静态整数校验和(跨度缓冲区){…}
我认为他的文章比我自己写答案更能说明问题
很简单。
您可以将
内存转到Span
,但不能反过来。在系统中应该有一个AsMemory()
方法。MemoryExtensions
类要做到这一点,不能进行测试,因为在手机上,AsMemory()
只接受字符串、数组、,和ArraySegment
s.As span live on stack必须使用ToArray()方法将其复制到堆中。数组隐式转换为ReadOnlyMemoryPut前面的短单词,以节省其他人的时间。