Я рефакторинг своїх бібліотек, щоб використовувати, Span<T>
щоб уникнути розподілу купи, якщо це можливо, але, оскільки я націлюю також на більш старі рамки, я також реалізую деякі загальні резервні рішення. Але зараз я виявив дивну проблему, і я не зовсім впевнений, знайшов помилку в .NET Core 3 чи роблю щось незаконне.
Питання:
// 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;
}
Цікаво, що він ReinterpretOld
добре працює в .NET Framework і в .NET Core 2.0 (тому я міг би бути задоволений цим все-таки), все-таки це мене трохи турбує.
Btw. ReinterpretOld
можна також виправити в .NET Core 3.0 невеликою модифікацією:
//return *(uint*)bytes;
uint* asUint = (uint*)bytes;
return *asUint;
Моє запитання:
Це помилка чи ReinterpretOld
працює у старих рамках лише випадково, і чи потрібно застосовувати виправлення також до них?
Зауваження:
- Збірка налагодження працює також у .NET Core 3.0
- Я намагався застосувати
[MethodImpl(MethodImplOptions.NoInlining)]
до ,ReinterpretOld
але це не мало ніякого ефекту.
stackalloc
(тобто він не
return Unsafe.As<byte, uint>(ref bytes[0]);
абоreturn MemoryMarshal.Cast<byte, uint>(bytes)[0];
- не потрібно використовуватиGetPinnableReference()
; Хоча, дивлячись на інший шматочок