Span<T>
可能な場合はヒープ割り当てを回避するために使用するライブラリをリファクタリングしていますが、古いフレームワークも対象としているため、いくつかの一般的なフォールバックソリューションも実装しています。しかし今、私は奇妙な問題を発見しました。.NETCore 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でうまく機能します(結局、満足できるかもしれません)が、それでも少し気になります。
ところで 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()
。ただし、他のビットを調べます