2016-08-17 53 views
0

我試圖使用BitConverter.GetBytes來獲取不同類型的不同對象的字節。爲了做到這一點,我想寫一個通用的擴展方法,而不是爲我想要使用的每種類型(短,長,ulong等)編寫單獨的擴展方法。使用BitConverter.GetBytes的通用方法

這可能嗎?

這裏的(不工作)的代碼,我至今對泛型方法:

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

你能否澄清你所說的「翻轉所得的字節」是什麼意思?你的Array.Reverse將翻轉數組中字節的順序,但不是字節本身中的值,這正是我認爲你的意思。或者你的意思是不按所有字節進行按位操作?在這種情況下翻轉可能意味着一些事情。 – Cody

+0

我真的希望編輯沒有大膽「翻轉」。這不是真正的問題,我甚至不應該把它包括在這個例子中。編輯澄清... –

+0

請澄清你的意思是「不工作」。 –

回答

1

它不建議,但你可以動態調用該方法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

使用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上給出錯誤的大小。

我rewritte 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; 
}