Generic BitConverter.GetBytes for primitive data types?
So I know there is this question addressing the need for getting the bytes of an object. But I am wondering if there is an approach to calling BitConverter.GetBytes
on a generic type where I know the type is a primitive (Int32, UInt16, etc).
Because people love silly examples as a prerequisite to actually answering questions here:
Public Sub Foobar(Of T as Structure)()
Dim x as T 'Assume T is declared as Int32
Dim y() as Byte
y = System.BitConverter.GetBytes(x)
End Sub
The above will throw your usual error:
Overload resolution failed because no accessible 'GetBytes' can be called with these arguments:
'Public Shared Function GetBytes(value As Double) As Byte()': Value of type 'T' cannot be converted to 'Double'.
'P开发者_JS百科ublic Shared Function GetBytes(value As Single) As Byte()': Value of type 'T' cannot be converted to 'Single'.
'Public Shared Function GetBytes(value As ULong) As Byte()': Value of type 'T' cannot be converted to 'ULong'.
'Public Shared Function GetBytes(value As UInteger) As Byte()': Value of type 'T' cannot be converted to 'UInteger'.
'Public Shared Function GetBytes(value As UShort) As Byte()': Value of type 'T' cannot be converted to 'UShort'.
'Public Shared Function GetBytes(value As Long) As Byte()': Value of type 'T' cannot be converted to 'Long'.
'Public Shared Function GetBytes(value As Integer) As Byte()': Value of type 'T' cannot be converted to 'Integer'.
'Public Shared Function GetBytes(value As Short) As Byte()': Value of type 'T' cannot be converted to 'Short'.
'Public Shared Function GetBytes(value As Char) As Byte()': Value of type 'T' cannot be converted to 'Char'.
'Public Shared Function GetBytes(value As Boolean) As Byte()': Value of type 'T' cannot be converted to 'Boolean'.
One solution I think would work is a large Select Case calling GetType(), but that is horrendously slow (because of boxing) and looks ugly. I would think that since I call my higher level class with a primitive data type for T
, that the compiler would be smart enough to figure it out, but I assume I am not providing enough information for it to derive what T's underlying value is at compile time for the invoked instances.I had a similar problem and solved it by converting the generic T type into an object first and then call the BitConverter.GetMethod(), i.e.
Dim obj As Object = CType(Value, T)
Dim bytes As Byte() = BitConverter.GetBytes(obj)
Solved it myself.
Using a stripped-down version of the solution provided in my question, "Faster way to convert from a String to generic type T when T is a valuetype?", I was able to to create an extension method to a generic type called GenericGetBytes
that would use the same delegate tricks to access the appropriate GetBytes
method in the System.BitConverter
class. This would preserve a decent amount of performance without me having to write up a bunch of overloaded functions for each type.
Code:
<System.Runtime.CompilerServices.Extension()>
Friend Function GenericGetBytes(Of T As Structure)(ByVal value As T) As Byte()
Return GenericBitConverter(Of T).GetBytes(value)
End Function
Private Class GenericBitConverter(Of T As Structure)
Private Sub New()
End Sub
Friend Delegate Function GetBytesFunc(ByVal value As T) As Byte()
Friend Shared ReadOnly GetBytes As GetBytesFunc = FetchGetBytesFunc()
Private Shared Function FetchGetBytesFunc() As GetBytesFunc
Return DirectCast(GetBytesFunc.CreateDelegate(GetType(GetBytesFunc),
GetType(BitConverter).GetMethod("GetBytes", New Type() {GetType(T)})),
GetBytesFunc)
End Function
End Class
Invocation:
Public Sub Foobar(Of T As Structure)(ByVal value As T)
Debug.Print(BitConverter.ToString(value.GenericGetBytes))
End Sub
Call Foobar(Of Int16)(42)
Output:
2A-00
Edit: And then I discover that the CType operator cannot convert from a base class to a derived class, which means the entire goal of this question and answer just became moot, as I have to move all my CType operators back to the derived classes. Hah.
精彩评论