tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルByte型の整数型的な使用について
記事No11805
投稿日: 2017/03/19(Sun) 10:51
投稿者OrientalMelody
いつもお世話になっております。

以前から疑問に思っていたのですが、Byte型は整数型のような使い方をしても
問題無いものなのでしょうか?

Byte型配列にして、RS232C受信した文字列を格納的な使い方もよく行っていますが、
0,1,2のように短整数型よりも狭い範囲のみで使用したいので。

やはり列挙体作った方が良いのでしょうかね?

使用メモリはByte型は1バイト、短整数型は2バイトですので、
そのあたりも気になりました。

何かご存知の方がいらっしゃいましたら、ご教示のほど、よろしくお願いいたします。

使用OS、言語:Windows7 64bit、VB2015

[ツリー表示へ]
タイトルRe: Byte型の整数型的な使用について
記事No11806
投稿日: 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

実際に使うとなると、他の演算子も実装したりしなければならず、
面倒な割に実入りが少ない方法とは思いますけれどね。

[ツリー表示へ]
タイトルRe^2: Byte型の整数型的な使用について
記事No11822
投稿日: 2017/04/14(Fri) 15:13
投稿者OrientalMelody
魔界の仮面弁士様

ご回答有難うございます。

遅レスになってしまい、申し訳ございません。

> 列挙型の場合は、変数の型として利用できるのがメリットですが、
> 範囲外の値を代入できないわけでは無いので、結局は利用時に
> System.Enum.IsDefined 等でのチェックは必要になってきます。
そうだったのですね。
先ほど、サンプルプログラムを作って確認してみました。
確かに範囲外の値も入力できますね。
範囲外の値は入らない方がもちろん良いのですが、
どちらかというと、IntelliSense入力候補に表示されることにより、
入力ミス防止や意味を分かりやすくするのが大きな目的でもあります。
ですので、今回はとりあえずこれで良しとします。

チェック用ソース例も記述頂きまして、大変有難うございました。

[ツリー表示へ]