使用BitConverter.GetBytes的通用方法

时间:2016-08-17 20:42:13

标签: c# generics bitconverter

我试图使用BitConverter.GetBytes获取不同类型的不同对象的字节数。为了做到这一点,我想编写一个通用扩展方法,而不是为我想要使用的每种类型(short,long,ulong等)编写单独的扩展方法。

这可能吗?

这是我到目前为止通用方法的(不工作)代码:

public static byte[] Foo<T>(this T input) where T : struct
{
    // error here, no match to overloads
    var result = BitConverter.GetBytes(input);
    // do more logic here...
    return result;
}

顺便说一句,这必须符合.NET 3.5。

2 个答案:

答案 0 :(得分:2)

没有建议,但您可以动态调用BitConverter.GetBytes方法:

public static byte[] ToFlipped<T>(T input) where T : struct
{
    var result = (byte[])typeof(BitConverter).GetMethod("GetBytes", new[] { typeof(T) })
        .Invoke(null, new[] { input });
    Array.Reverse(result);

    return result;
}

答案 1 :(得分:1)

使用GCHandle.Alloc()并固定结构: - )

public static byte[] Foo<T>(this T input) where T : struct
{
  int size = Marshal.SizeOf(typeof(T));
  var result = new byte[size];
  var gcHandle = GCHandle.Alloc(input, GCHandleType.Pinned);
  Marshal.Copy(gcHandle.AddrOfPinnedObject(), result, 0, size);
  gcHandle.Free();
  return result;
}

...但是“Marshal.SizeOf”在bool和char上给出了错误的大小。

我已经重写了SizeOf函数(看起来有点疯狂,但速度极快)

static readonly Dictionary<long, int> SizeOfDict = new Dictionary<long, int>();

//[MethodImpl(MethodImplOptions.AggressiveInlining)] // not supported below 4.5
public static int SizeOf<T>() where T : struct
{
  // --- Highspeed Compiler-Hack ---
  // if (typeof(T) == typeof(byte)) return sizeof(byte); // uncomment if .Net >= 4.5
  // if (typeof(T) == typeof(sbyte)) return sizeof(sbyte);
  // if (typeof(T) == typeof(ushort)) return sizeof(ushort);
  // if (typeof(T) == typeof(short)) return sizeof(short);
  // if (typeof(T) == typeof(uint)) return sizeof(uint);
  // if (typeof(T) == typeof(int)) return sizeof(int);
  // if (typeof(T) == typeof(ulong)) return sizeof(ulong);
  // if (typeof(T) == typeof(long)) return sizeof(long);
  // if (typeof(T) == typeof(float)) return sizeof(float);
  // if (typeof(T) == typeof(double)) return sizeof(double);
  // --- fix wrong sizes ---
  if (typeof(T) == typeof(char)) return sizeof(char);
  if (typeof(T) == typeof(bool)) return sizeof(bool);
  long id = (long)typeof(T).TypeHandle.Value;
  int len;
  if (!SizeOfDict.TryGetValue(id, out len))
  {
    len = Marshal.SizeOf(typeof(T));
    SizeOfDict.Add(id, len);
  }
  return len;
}