如何从Span <t>创建Memory <t>?

时间:2018-06-29 19:53:51

标签: c# .net .net-core

ReadOnlySpan<char>版本外,我正在尝试重载解析方法以使用string参数。问题在于该实现将Dictionary<string, T>用于解析逻辑。

我尝试将其切换为Dictionary<ReadOnlySpan<char>, T>,但由于它是仅堆栈对象,因此不允许将其作为ReadOnlySpan<char>用作通用参数。然后,我将其切换为使用允许的ReadOnlyMemory<char>。然后,我实现了一个基本的Ordinal比较器,但是现在很难从ReadOnlyMemory<char>参数创建ReadOnlySpan<char>了。这可能吗?

更新

看来这是不可能的。为了支持我在上面发布的方案,我将更改字典以使其具有一个int键,该键是ReadOnlySpan<char>的哈希码,并将该值设为包含嵌入在元素中的字符串的列表,并且必须手动解析哈希码冲突。

1 个答案:

答案 0 :(得分:5)

有一篇很棒的文章介绍了MSDN Magazine article上的Span<T>

  

Span<T>实例只能在堆栈上,而不能在堆上。 这意味着您无法装箱跨度((例如,Span<T>不能与现有的反射调用API一起使用,因为它们需要装箱)。这意味着您不能在类中甚至没有类似非引用的结构中都拥有Span<T>字段。这意味着您不能在可能会隐式成为类中字段的地方使用跨度,例如通过将它们捕获到lambda或在异步方法或迭代器中作为局部变量(因为这些“局部变量”可能最终会成为编译器生成的字段)状态机。)这也意味着您不能将Span<T>用作通用参数,因为该类型参数的实例可能最终被装箱或以其他方式存储到堆中(并且目前没有“ where T : ref struct ”约束可用)。

     

...

     

您可以从数组创建Memory<T>并将其切片   会跨度,但是它是一个(非引用类)结构,并且可以在   堆。然后,当您想要进行同步处理时,可以得到一个   Span<T>,例如:

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) { ... }

我认为他的文章比我写自己的答案更好。


简单

您可以从Memory<T>Span<T>,但不能相反。