我在工作中遇到了类似下面这样的东西。我以前从未使用过如此频繁地使用结构体的 C# 代码库。
我之前使用过 fixed ,以防止垃圾回收器在我使用指针进行不安全操作时移动对象。但我从未见过它被用于将指针传递给 Span,然后在 fixed 语句之外使用 Span。
这样可以吗?我猜因为 Span 是托管的,一旦我们将位置传递给它,如果 GC 移动 MyStruct 的位置,那么它应该能正确获取新位置,对吗?
[StructLayout(LayoutKind.Sequential)]
public unsafe struct MyInnerStruct
{
public uint InnerValueA;
public uint InnerValueB;
public float InnerValueC;
public long InnerValueD;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct MyStruct
{
public MyInnerStruct Value0;
public MyInnerStruct Value1;
public MyInnerStruct Value2;
public MyInnerStruct Value3;
public MyInnerStruct Value4;
public MyInnerStruct Value5;
public MyInnerStruct Value6;
public MyInnerStruct Value7;
public MyInnerStruct Value8;
public MyInnerStruct Value9;
public int ValidValueCount;
public Span<MyInnerStruct> Values
{
get
{
fixed (MyInnerStruct* ptr = &Value0)
{
return new Span<MyInnerStruct>(ptr, ValidValueCount);
}
}
}
}
GCHandle.Alloc
。 - CharlesSpan<T>
只设计用于本地变量,不应该以这种方式使用。 - CharliefaceMyStruct
不知道它的存储位置,所以不能保证。你真的应该从包含对象中执行此操作。你也可以使用return MemoryMarshal.CreateSpan<MyInnerStruct>(ref Value0, ValidValueCount);
来避免使用unsafe
,尽管同样需要注意:你需要小心不要泄漏堆栈指针。 - Charliefacepublic static Span<T> CreateSpan<T>(ref T reference, int length) => new Span<T>(ref reference, length);
。 - Michael Covelli