开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜