2016-08-01 8 views
0

データのパケットを構成するために16進数の文字列を返す次の関数がありますが、値はバイト、UShort、Integer、Single、Stringのいずれかです。Vb.net汎用関数は型を変換できませんT

Public Function GetWriteString(ByVal op As Operation, ByVal value As UShort) As String 
    Dim dataString As String = DATA_CONST & WRITE_CONST & op.ToString(Operation.Accessibility.WRITE) & ToHex(value) 
    Dim byteCount As String = ToHex(GetByteCount(dataString)) 
    Return headerString & byteCount & CRC_Module.HeaderCRC(headerString & byteCount) & dataString & CRC_Module.DataCRC(dataString) 
End Function 

が、私はそれが常に同じであるため、一般的な機能の関数を作りたい、唯一の違いは、ToHex(value)部分があります。 ToHex関数は、上記で指定した各データ型のオーバーロードされた関数なので、値に応じて異なる文字列を返します。 公開機能ToHex(バイトとして進)文字列として:型の値Iは、関数は汎用的にしようとすると

Public Function GetWriteString(Of T)(ByVal op As Operation, ByVal value As T) As String 
    Dim dataString As String = DATA_CONST & WRITE_CONST & op.ToString(Operation.Accessibility.WRITE) & ToHex(value) 
    Dim byteCount As String = ToHex(GetByteCount(dataString)) 
    Return headerString & byteCount & CRC_Module.HeaderCRC(headerString & byteCount) & dataString & CRC_Module.DataCRC(dataString) 
End Function 

それにはアクセス可能 『ToHex』はこれらの引数で呼び出されることができませんので、オーバーロードの解決に失敗しました」と言いますオーバーロードされたToHex関数のそれぞれについて、 'T'を 'Byte'に変換することはできません。この関数を一般的にする方法はありますか?もしそうなら、これを最善の方法としていますか、関数のパラメーターに明示的に5つの異なる関数を作成する必要がありますか?

ToHex機能:

Public Function ToHex(ByVal characters As String) As String 
    ' Variables 
    ' byteArray - An array of bytes used to hold the characters which were converted to bytes 
    Dim byteArray As Byte() = defaultEncoding.GetBytes(characters) 
    ' Converts the byte array to a string of hex values 
    Return BitConverter.ToString(byteArray).Replace("-", "") 
End Function 

Public Function ToHex(ByVal hex As Byte) As String 
    Return hex.ToString("X2") 
End Function 

Public Function ToHex(ByVal word As UShort) As String 
    Return word.ToString("X4") 
End Function 

Public Function ToHex(ByVal int As Integer) As String 
    Return int.ToString("X8") 
End Function 

''' <summary> 
''' Converts a float to a string of hex bytes 
''' </summary> 
''' <param name="float">A float value to be converted</param> 
''' <returns>A string of hex bytes</returns> 
Public Function ToHex(ByVal float As Single) As String 
    ' Variables 
    ' byteArray - An array of bytes used to hold the bytes that make up the floating point 
    Dim byteArray = defaultEncoding.GetBytes(float) 
    ' Reverses the byte array 
    Array.Reverse(byteArray) 
    ' Converts the byte array to a string of hex values 
    Return BitConverter.ToString(byteArray).Replace("-", "") 
End Function 
+0

私は種類ごとに独自の過負荷を考えますより明確で維持可能なアプローチになります。 – Fabio

+0

ToHexとは何ですか?それは組み込み関数なのか、それともあなたが書いたものなのでしょうか?それを一般的なものにするか、単に 'Object'を受け入れるようにする必要があります。ここでジェネリックを使用することはすべて便利だとは思いません。 – sstan

+0

ジェネリックを引き続き使用する場合、ToHexメソッドは、渡される型を決定するために 'If'または' Select'文を使用する必要があります。 – Fabio

答えて

0

あなたのToHex関数はオブジェクトを取る作ることができます。これは、すべてのプリミティブ型で1つの関数を持つ唯一の方法です。なぜなら、すべてのプリミティブ型は1つの共通の基本型、つまりオブジェクトを共有するからです。これはDateTimeでは機能しませんが、ケースを追加できます。注:何かをこの関数に渡すことができるので、あなたのプロジェクトでそれを持つことは本当に良い考えではありません。しかし、それはあなたが望むものを少なくとも達成するはずです。

Option Strict Off 

<Runtime.CompilerServices.Extension> 
Public Function ToHex(input As Object) As String 
    Dim defaultEncoding = System.Text.Encoding.Default 
    Dim result As String 
    Dim byteArray As Byte() 
    If TypeOf (input) Is String Then 
     byteArray = defaultEncoding.GetBytes(input) 
     result = BitConverter.ToString(byteArray).Replace("-", "") 
    Else 
     Dim byteCount = System.Runtime.InteropServices.Marshal.SizeOf(input) 
     If (TypeOf (input) Is Single) OrElse (TypeOf (input) Is Double) OrElse (TypeOf (input) Is Decimal) Then 
      byteArray = BitConverter.GetBytes(input) 
      Array.Reverse(byteArray) 
      result = BitConverter.ToString(byteArray).Replace("-", "").PadLeft(byteCount * 2, "0") 
     Else 
      result = CLng(input).ToString("X").PadLeft(byteCount * 2, "0") 
     End If 
    End If 
    Return result 
End Function 

テストこの:

Console.WriteLine("Single: " & Single.MaxValue.ToHex()) 
Console.WriteLine("Single: " & 1.0F.ToHex()) 

Console.WriteLine("Integer: " & Integer.MaxValue.ToHex()) 
Console.WriteLine("Integer: " & 1I.ToHex()) 
Console.WriteLine("Integer: " & 1I.ToString("X8")) 

Console.WriteLine("UShort: " & UShort.MaxValue.ToHex()) 
Console.WriteLine("UShort: " & 1US.ToHex()) 
Console.WriteLine("UShort: " & 1US.ToString("X4")) 

Console.WriteLine("String: " & "String".ToHex()) 

シングル:7F7FFFFF
シングル:3F800000
整数:7FFFFFFF
整数:00000001
整数:00000001
USHORT:FFFF
USHORT:0001
USHORT:0001
文字列:537472696E67

あなたがオブジェクトを拡張したくない場合は、あなたが<Extension>を削除し、それを呼び出すことができますToHex(Single.MaxValue)

のような私たちはのようなもののためにあなたがここにhttps://stackoverflow.com/search?q=numeric+generic+C%23

+0

このコードは先行ゼロが付いているデータでは機能しませんでした。先行ゼロが必要です。たとえば、値8がUShortとして渡された場合、返される文字列は「8」ですが、「0008」が必要ですが、バイトとして渡された場合は「08」が返されます。 – Logan

+0

ロジック先行0の数は? – djv

+0

バイトタイプの場合、UShortには1バイト(00)、2バイト(0000)、整数とシングルには4バイト(00000000)、文字列には1バイトが必要です – Logan

0

たい正確に何を達成できない理由を参照してください。ケース(または私がそれについて理解しているもの)は、私はそれが自分の(私的な)方法で共通のものを入れ、ちょうど公共のものから正しい "ヘクスド"値で呼び出すでしょう。
このようにして、コアコードを移動し、重複したコードを単純化すると、それをバイパスできません(BCLチームがEnumerableに対してどのように異なるオーバーロードを行ったかを見てください。exempleマックス)

Public Function GetWriteString(op As Operation, value As UShort) As String 
    Return GetWriteStringInternal(op, ToHex(value)) 
End Function 

Public Function GetWriteString(op As Operation, value As Byte) As String 
    Return GetWriteStringInternal(op, ToHex(value)) 
End Function 

Public Function GetWriteString(op As Operation, value As Integer) As String 
    Return GetWriteStringInternal(op, ToHex(value)) 
End Function 

Public Function GetWriteString(op As Operation, value As Single) As String 
    Return GetWriteStringInternal(op, ToHex(value)) 
End Function 

Public Function GetWriteString(op As Operation, value As String) As String 
    Return GetWriteStringInternal(op, ToHex(value)) 
End Function 

Private Function GetWriteStringInternal(op As Operation, hexValue As String) As String 
    Dim dataString As String = DATA_CONST & WRITE_CONST & op.ToString(Operation.Accessibility.WRITE) & hexValue 
    Dim byteCount As String = ToHex(GetByteCount(dataString)) ' Call the Integer overload if I've understood 
    Return headerString & byteCount & CRC_Module.HeaderCRC(headerString & byteCount) & dataString & CRC_Module.DataCRC(dataString) 
End Function 

注意点としてシングル用ToHexの過負荷が私のために動作しません(おそらく私のためであることstrictオプションに関連する)

関連する問題