在 .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 不再是副本,而是对原始文件的引用。