Estoy refactorizando mis bibliotecas para usarlas Span<T>
para evitar las asignaciones de almacenamiento dinámico, si es posible, pero al apuntar también a marcos más antiguos, también estoy implementando algunas soluciones de respaldo generales. Pero ahora encontré un problema extraño y no estoy muy seguro de si encontré un error en .NET Core 3 o si estoy haciendo algo ilegal.
La cuestión:
// This returns 1 as expected but cannot be used in older frameworks:
private static uint ReinterpretNew()
{
Span<byte> bytes = stackalloc byte[4];
bytes[0] = 1; // FillBytes(bytes);
// returning bytes as uint:
return Unsafe.As<byte, uint>(ref bytes.GetPinnableReference());
}
// This returns garbage in .NET Core 3.0 with release build:
private static unsafe uint ReinterpretOld()
{
byte* bytes = stackalloc byte[4];
bytes[0] = 1; // FillBytes(bytes);
// returning bytes as uint:
return *(uint*)bytes;
}
Curiosamente, ReinterpretOld
funciona bien en .NET Framework y en .NET Core 2.0 (por lo que podría estar contento con él después de todo), aún así, me molesta un poco.
Por cierto. ReinterpretOld
se puede arreglar también en .NET Core 3.0 mediante una pequeña modificación:
//return *(uint*)bytes;
uint* asUint = (uint*)bytes;
return *asUint;
Mi pregunta:
¿Es esto un error o ReinterpretOld
funciona en marcos anteriores solo por accidente y debo aplicar la solución también para ellos?
Observaciones:
- La compilación de depuración también funciona en .NET Core 3.0
- I intentado aplicar
[MethodImpl(MethodImplOptions.NoInlining)]
aReinterpretOld
pero no tuvo ningún efecto.
stackalloc
(es decir, no borra el espacio asignado)
return Unsafe.As<byte, uint>(ref bytes[0]);
oreturn MemoryMarshal.Cast<byte, uint>(bytes)[0];
- no es necesario usarGetPinnableReference()
; sin embargo, mirando a la otra parte