我尝试将一个结构转换到 Span 并返回(以便可以更改原始结构)。这部分起作用了。如何将 Span 转换回结构体(不要复制)?
这是我的尝试。不幸的是,它在回传时不起作用:
internal struct TestStruct
{
internal byte ByteValue;
internal ushort UshortValue;
internal uint UintValue;
internal ulong UlongValue;
internal TestStruct(byte byteValue,ushort ushortValue, uint uintValue, ulong ulongValue) {
ByteValue = byteValue;
UshortValue = ushortValue;
UintValue = uintValue;
UlongValue = ulongValue;
}
}
class Program
{
static void Main(string[] args) {
TestStruct structInstance = new TestStruct( 0xAA, 0xAAAA, 0xAAAAAAAA, 0xAAAAAAAAAAAAAAAA );
var span1 = MemoryMarshal.CreateSpan<TestStruct>(ref structInstance, 1);
span1[0].ByteValue = 0x11;
Debug.WriteLine($"span1[0].ByteValue = 0x11 => 0x{structInstance.ByteValue:X2}");
var byteSpan1 = MemoryMarshal.AsBytes<TestStruct>(span1);
byteSpan1[0] = 0x22;
Debug.WriteLine($"byteSpan1[0] = 0x22 => 0x{structInstance.ByteValue:X2}");
TestStruct structAgain = MemoryMarshal.AsRef<TestStruct>(byteSpan1);
structAgain.ByteValue = 0xBB;
Debug.WriteLine($"structAgain.ByteValue = 0xBB => 0x{structInstance.ByteValue:X2}");
}
}
结果:
span1[0].ByteValue = 0x11 => 0x11
byteSpan1[0] = 0x22 => 0x22
structAgain.ByteValue = 0xBB => 0x22
显然MemoryMarshal.AsRef()给出了一个副本并且没有强制转换。有办法让它工作吗?
最佳答案
您遇到的问题是struct
是一个值类型。这意味着,每个结构体字段/参数/局部变量都包含该结构体的整个值。您的TestStruct structAgain
是您原件 structInstance
的独立副本。对副本的更改不会影响原始版本,反之亦然。
您想要的是对原始结构的引用。为此,您需要 ref
关键词。如果你看MemoryMarshal.AsRef ,你看到返回类型是 ref T
。这意味着它正在返回一个引用。您可以通过将局部变量声明为ref TestStruct structAgain = ref MemoryMarshal.AsRef<TestStruct>(byteSpan1);
来保存引用。 。现在 structAgain 不再是副本,而是对原始版本的引用。
关于c# - 在 .C# 和 NET 5 中,在 struct 和 Span<byte> 之间进行无不安全的转换,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66068340/