I try to cast a struct to a Span and back (so that the original struct can be changed). That worked partially. How can I cast the Span back into a struct (don't copy) ?
Here is my try. Unfortunately it doesn't work when casting back:
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}");
}
}
Result:
span1[0].ByteValue = 0x11 => 0x11
byteSpan1[0] = 0x22 => 0x22
structAgain.ByteValue = 0xBB => 0x22
Obviously MemoryMarshal.AsRef () gives a copy and does not cast. Is there a way to get it working?
The problem you are running into is that struct
is a value type. This means, each struct field/parameter/local variable contains the entire value of the struct. Your TestStruct structAgain
is an independent copy of your original structInstance
. Changes to the copy do not affect the original, and vice versa.
What you want is a reference to your original struct. To do this, you need the ref
keyword. If you look at MemoryMarshal.AsRef, you see the return type is ref T
. This means it is returning a reference. You can save the reference by declaring your local variable as ref TestStruct structAgain = ref MemoryMarshal.AsRef<TestStruct>(byteSpan1);
. Now structAgain is no longer a copy, but a reference to the original.