我试图使用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。
答案 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;
}