Если вы используете последнюю версию .NET, вы можете использовать Span<T>
(System.Buffers) для этого:
class MyClass<T> where T : struct
{
public T Value = default(T);
public MyClass(byte[] bytes)
{
Value = MemoryMarshal.Cast<byte, T>(bytes)[0];
}
}
Вы также можете использовать unsafe
в последних версиях C #(для ограничения T : unmanaged
):
class MyClass<T> where T : unmanaged
{
public T Value = default(T);
public unsafe MyClass(byte[] bytes)
{
fixed (byte* ptr = bytes)
{
Value = *(T*)ptr; // note: no out-of-range check here; dangerous
}
}
}
Вы можете также сделать некоторые вещи здесь, используя Unsafe.*
методы (System.Runtime.CompilerServices.Unsafe);например (обратите внимание, нет ограничений):
class MyClass<T>
{
public T Value = default(T);
public unsafe MyClass(byte[] bytes)
{
T local = default(T);
fixed (byte* ptr = bytes)
{
Unsafe.Copy(ref local, ptr); // note: no out-of-range check here; dangerous
}
Value = local;
}
}
Если вы хотите проверить проблему вне диапазона:
if (bytes.Length < Unsafe.SizeOf<T>())
throw new InvalidOperationException("Not enough data, fool!");
или вы можете использовать sizeof(T)
, если у вас естьT : unmanaged
ограничение.Вам не нужно это с решением Span<T>
(первым), потому что исходный Cast<byte, T>
в этом сценарии даст нулевой интервал длины, а [0]
сгенерирует соответственно.
Я думаю это тоже должно сработать!
public unsafe MyClass(byte[] bytes)
{
Value = Unsafe.As<byte, T>(ref bytes[0]); // note: no out-of-range check here; dangerous
}
полный пример (работает на net462):
using System;
using System.Runtime.CompilerServices;
struct Foo
{
public int x, y;
}
class MyClass<T>
{
public T Value = default(T);
public unsafe MyClass(byte[] bytes)
{
if (bytes.Length < Unsafe.SizeOf<T>())
throw new InvalidOperationException("not enough data");
Value = Unsafe.As<byte, T>(ref bytes[0]);
}
}
static class P
{
static void Main() {
byte[] bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
var obj = new MyClass<Foo>(bytes);
var val = obj.Value;
Console.WriteLine(val.x); // 67305985 = 0x04030201
Console.WriteLine(val.y); // 134678021 = 0x08070605
}
}