我的类型可以保存一些本机内存。我想在其上实现AsSpan()
,以便可以安全地访问本机内存。
下面是一个幼稚的尝试,显示了我正在尝试做的事情。显然Span<T>
不会使Holder对象保持活动状态,因为它仅具有指向本机内存的指针,而没有对Holder对象的引用。我也尝试实现MemoryManager<T>
,但是我也看不出如何使Span<T>
使管理器对象保持活动状态。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
internal class Program
{
public static void Main()
{
Span<byte> span = GetSpan();
GC.Collect();
GC.WaitForPendingFinalizers();
span[span.Length - 1] = 0; // Access violation
}
private static Span<byte> GetSpan()
{
Span<byte> span = new Holder(1 << 20).AsSpan();
GC.Collect();
GC.WaitForPendingFinalizers();
span[span.Length - 1] = 0; // OK
return span;
}
}
public class Holder
{
private readonly int _size;
private readonly IntPtr _pointer;
public Holder(int size)
{
_size = size;
_pointer = Marshal.AllocHGlobal(_size);
}
~Holder()
{
Marshal.FreeHGlobal(_pointer);
Debug.WriteLine("{0:X} was freed", _pointer);
}
public Span<byte> AsSpan()
{
unsafe { return new Span<byte>((void*)_pointer, _size); }
}
}
Span<T>
能够使诸如String
或byte[]
之类的托管对象保持活动状态。有没有一种方法可以对本机内存持有人类型实现AsSpan()
,以便Span<T>
使持有人对象保持活动状态?
答案 0 :(得分:1)
对于每个this discussion,无法使用Span<T>
来控制非托管内存的生存期。
您可以实现MemoryManager<T>
来管理非托管内存的生存期,在using
块中使用它,并且只要Span<T>
不逃避using块,它会很安全的。 (但是不可能强迫API使用者安全使用API。)