在 .C# 和 NET 5 中,在 struct 和 Span<byte> 之间强制转换,反之亦然
Cast without unsafe between struct and Span<byte> and vice versa in .C# and NET 5
我尝试将结构强制转换 到 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
是值类型。这意味着,每个 struct field/parameter/local 变量都包含该结构的整个值。您的 TestStruct structAgain
是原始 structInstance
的独立副本。对副本的修改不会影响原件,反之亦然。
您需要的是对原始结构的引用。为此,您需要 ref
关键字。如果您查看 MemoryMarshal.AsRef,您会看到 return 类型是 ref T
。这意味着它是 returning 参考。您可以通过将局部变量声明为 ref TestStruct structAgain = ref MemoryMarshal.AsRef<TestStruct>(byteSpan1);
来保存引用。现在 structAgain 不再是副本,而是对原始文件的引用。
我尝试将结构强制转换 到 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
是值类型。这意味着,每个 struct field/parameter/local 变量都包含该结构的整个值。您的 TestStruct structAgain
是原始 structInstance
的独立副本。对副本的修改不会影响原件,反之亦然。
您需要的是对原始结构的引用。为此,您需要 ref
关键字。如果您查看 MemoryMarshal.AsRef,您会看到 return 类型是 ref T
。这意味着它是 returning 参考。您可以通过将局部变量声明为 ref TestStruct structAgain = ref MemoryMarshal.AsRef<TestStruct>(byteSpan1);
来保存引用。现在 structAgain 不再是副本,而是对原始文件的引用。