跨度和内存作为方法签名中数组的替代品?

Fre*_*red 9 c# c#-7.2

Spanin 方法替换参数?

我应该取代我所有的阵列(例如byte[]char[]string[]含)的参数在我的同步方法Span(如Span<byte>Span<char>Span<string>)?

例子:

public void Foo(byte[] bytes)
Run Code Online (Sandbox Code Playgroud)

和:

public void Foo(Span<byte> bytes)
Run Code Online (Sandbox Code Playgroud)

Memory异步方法替换参数?

我应该取代我所有的阵列(例如byte[]char[]string[]含)的参数在我的异步方法Memory(例如Memory<byte>Memory<char>Memory<string>)?

例子:

public async Task FooAsync(byte[] bytes)
Run Code Online (Sandbox Code Playgroud)

和:

public async Task FooAsync(Memory<byte> bytes)
Run Code Online (Sandbox Code Playgroud)

Spanin 方法替换返回类型?

我应该取代我所有的阵列(例如byte[]char[]string[]含)返回类型在我的方法Span(例如Span<byte>Span<char>Span<string>)?

例子:

public byte[] Foo()
Run Code Online (Sandbox Code Playgroud)

和:

public Span<byte> Foo()
Run Code Online (Sandbox Code Playgroud)

唔...

  • 数组作为方法参数是不受欢迎的吗?被Span青睐?
  • 数组作为返回类型是不受欢迎的吗?被Span青睐?

我读过几个有关的文章SpanReadOnlySpanMemory却发现这一切有点难以把握我微不足道的一点心意。是否有任何关于 Span 的经验法则或低能指南?

sne*_*sse 2

用方法中的参数替换Span

将参数替换为Memory异步方法中的参数?

用 in 方法替换返回类型Span

不,仅仅更改签名没有任何好处。它甚至可能会产生负面影响,因为每次调用都必须复制结构。Span<T>不重,但为什么要废物循环呢?

如果您正在方法内使用数组并且需要一个切片来处理或其他什么,请在需要的地方创建一个跨度。如果您确实有想要传递 a 的调用者Span<T>,请考虑更改签名(或重载)。

由于Span<T>只能存在于堆栈上,因此很难将它们传递给异步方法、迭代器或其他线程。

通常,考虑Span<T>作为指向数组的指针的替代方案。所以当你...时使用它们

  • 拥有明确定义所有权的不安全缓冲区(AllocHGlobal从/向外部 P/Invoke API 提供的数据、stackalloced 数据)
  • 有包含大量数组访问的热循环(这里您之前可能使用过指针)
  • 之前需要进行指针运算
  • 需要重新解释一些记忆 ( MemoryMarshal.Cast)
  • 需要数据保留在同一个线程上
  • 需要限制数据的生命周期

我还没有遇到任何我想使用的用例Memory<T>