タイトル | : Re: Byte型の整数型的な使用について |
記事No | : 11806 |
投稿日 | : 2017/03/19(Sun) 19:25 |
投稿者 | : 魔界の仮面弁士 |
> 以前から疑問に思っていたのですが、Byte型は整数型のような使い方をしても > 問題無いものなのでしょうか?
古いバージョンの VB で翻訳された時の名残で、Integer を整数型、Long を長整数型と呼んでいるだけで、 Byte も SByte も UShort も Short も UInteger も Integer も ULong も Long も整数型の一種ですよ。
https://msdn.microsoft.com/ja-jp/library/cc437193%28vs.71%29.aspx
> 使用メモリはByte型は1バイト、短整数型は2バイトですので、 > そのあたりも気になりました。
変数のサイズとしてはその通りですが、値の比較や代入処理など、 演算のタイミングに限ってみれば、IL アセンブリ的には Byte 型向けの専用命令があるわけではなく、 基本的に Int32 な値でやりとりされる仕様だったりします。
蛇足ですが、「Dim b As Byte = &HABC」という代入処理なども、詳細コンパイルオプションにて 『整数オーバーフローのチェックを解除(removeintchecks オプション)』すると動作が変わります。
解除時:変数 b に「&HABC And &HFF」相当の値すなわち &HBC が代入されます。 有効時:コンパイルエラーになります。(BC30439:"定数式は、型 'Byte' では表現できません。")
> Byte型配列にして、RS232C受信した文字列を格納的な使い方もよく行っていますが、 > 0,1,2のように短整数型よりも狭い範囲のみで使用したいので。 > やはり列挙体作った方が良いのでしょうかね?
処理効率で大差がないようであれば、あとでコードを見た時に 分かりやすいか・読みやすいかどうかで判断すれば良いのでは無いでしょうか。
0,1,2 の三値程度なら、Byte 型の定数を使うという手もありそうです。
列挙型の場合は、変数の型として利用できるのがメリットですが、 範囲外の値を代入できないわけでは無いので、結局は利用時に System.Enum.IsDefined 等でのチェックは必要になってきます。
あるいは、0〜2 しか扱えない型を作ったりもできます。
それにメリットがあるかと言われると微妙なところですが、ひとまず サンプルとして、TriInt という型を作ってみました。
Dim bin0 As Byte = TriInt.Zero Dim bin1 As Byte = TriInt.One Dim bin2 As Byte = TriInt.Two Dim bin3 As Byte = 3
Dim tri0a As TriInt = 0 Dim tri1a As TriInt = 1 Dim tri2a As TriInt = 2 Dim tri3a As TriInt = 3
Dim trit0b As TriInt = bin0 Dim trit1b As TriInt = bin1 Dim trit2b As TriInt = bin2 Dim trit3b As TriInt = bin3
上記でいうと、tri3a や tri3b への代入は範囲外の値として、 OverflowException となるようにしています。(Option Strict Off 時)
Option Strict On にした場合は、Intger→TryInt や Byte→TryInt への 縮小変換でエラー報告されるようになりますので、 Dim bit0b As TriInt = CType(bin0, TriInt) のように明示的型変換が要求されます。
Public Structure TriInt Private value As Byte Public Shared ReadOnly Zero As New TriInt() With {.value = 0} Public Shared ReadOnly One As New TriInt() With {.value = 1} Public Shared ReadOnly Two As New TriInt() With {.value = 2} Public Shared Widening Operator CType(b As TriInt) As Byte Return b.value End Operator
<DebuggerHidden> Public Shared Narrowing Operator CType(b As Byte) As TriInt If b <= 2 Then Return New TriInt() With {.value = b} Else Throw New OverflowException("0〜2の範囲外です。") End If End Operator
<DebuggerHidden> Public Shared Narrowing Operator CType(b As Integer) As TriInt If b <= 2 Then Return New TriInt() With {.value = CByte(b)} Else Throw New OverflowException("0〜2の範囲外です。") End If End Operator End Structure
実際に使うとなると、他の演算子も実装したりしなければならず、 面倒な割に実入りが少ない方法とは思いますけれどね。
|