Tôi đang cấu trúc lại các thư viện của mình để sử dụng Span<T>
để tránh phân bổ heap nếu có thể nhưng vì tôi cũng nhắm mục tiêu các khung cũ hơn nên tôi cũng đang thực hiện một số giải pháp dự phòng chung. Nhưng bây giờ tôi đã tìm thấy một vấn đề kỳ lạ và tôi không chắc là mình đã tìm thấy một lỗi trong .NET Core 3 hay tôi đang làm gì đó bất hợp pháp.
Vấ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;
}
Thật thú vị, ReinterpretOld
hoạt động tốt trong .NET Framework và .NET Core 2.0 (vì vậy tôi có thể hài lòng với nó sau tất cả), tuy nhiên, điều đó làm phiền tôi một chút.
Btw. ReinterpretOld
cũng có thể được sửa trong .NET Core 3.0 bằng một sửa đổi nhỏ:
//return *(uint*)bytes;
uint* asUint = (uint*)bytes;
return *asUint;
Câu hỏi của tôi:
Đây có phải là một lỗi hoặc chỉ ReinterpretOld
hoạt động trong các khung cũ hơn một cách tình cờ và tôi có nên áp dụng bản sửa lỗi cho chúng không?
Nhận xét:
- Bản dựng gỡ lỗi cũng hoạt động trong .NET Core 3.0
- Tôi cố gắng để áp dụng
[MethodImpl(MethodImplOptions.NoInlining)]
đếnReinterpretOld
nhưng nó không có hiệu lực.
stackalloc
(tức là nó không xóa sạch không gian được phân bổ)
return Unsafe.As<byte, uint>(ref bytes[0]);
hoặcreturn MemoryMarshal.Cast<byte, uint>(bytes)[0];
- không cần sử dụngGetPinnableReference()
; Tuy nhiên, nhìn vào một chút khác