.NETで賢くなったVB(構造体)

■ VB6までの構造体はただの変数リストを羅列するだけでしたが、.net以降ではインターフェイスを実装できるようになったので、ほとんどクラスと変わりない実装ができるようになりました。 無論、クラスと異なる点も多々ありますが、「賢くなった構造体はどうよ?」と言う訳で、下記のサンプルを作ってみました。

'シンプルな構造体
Public Structure stRGB
  Public R, G, B As Byte
End Structure

'高度な構造体
Public Structure stRGB
  Public R, G, B As Byte

  'グレイスケール化時の係数
  Private Const BRK As Single = 0.298912
  Private Const BGK As Single = 0.586611
  Private Const BBK As Single = 0.114478

  'Clear
  Public Sub Clear()
    R = 0
    G = 0
    B = 0
  End Sub

  'Brightness
  Public Function Brightness() As Single
    Return CSng((R + G + B) * (1 / 3))
  End Function

  'GrayScale
  Public Function GrayScale() As Byte
    Return CByte(Fix(R * BRK + G * BGK + B * BBK))
  End Function

  'ans = a + b
  Public Shared Operator +(ByVal A As stRGB, ByVal B As stRGB) As stRGB
    Dim res As stRGB
    Try
      res.R = A.R + B.R
      res.G = A.G + B.G
      res.B = A.B + B.B
      Return res
    Catch ex As Exception
      Return Nothing
    End Try
  End Operator

  'ans = a / b
  Public Shared Operator /(ByVal A As stRGB, ByVal B As Integer) As stRGB
    Dim res As stRGB
    Try
      res.R = CByte(A.R / B)
      res.G = CByte(A.G / B)
      res.B = CByte(A.B / B)
      Return res
    Catch ex As Exception
      Return Nothing
    End Try
  End Operator

End Structure

 「シンプルな構造体」の宣言では、バイト型の変数を3コ用意しているだけのメンバ構成で、VB6で宣言可能なものです。
 「高度な構造体」の宣言では、メソッドやオペレータを含み、構造体に対する演算が内包されています。

 で、この違いがどう影響するかというと、

'シンプルな構造体宣言の場合
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
  Handles Button1.Click

  Dim ST, ET As Double

  ST = QPF.GetMilliTime

  Dim C(VOL - 1) As stRGB
  Dim sum As stRGB=C(0)
  For n = 1 To VOL - 1
    sum.R = CByte((sum.R + C(n).R) / 2)
    sum.G = CByte((sum.G + C(n).G) / 2)
    sum.B = CByte((sum.B + C(n).B) / 2)
  Next

  ET = QPF.GetMilliTime - ST

  Me.TextBox1.Text = ET.ToString("#,##0.000") '+ "ms"
End Sub

'高度な構造体宣言の場合
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
  Handles Button1.Click

  Dim ST, ET As Double

  ST = QPF.GetMilliTime

  Dim C(VOL - 1) As stRGB
  Dim sum As stRGB = C(0)
  For n = 1 To VOL - 1
    sum = (sum + C(n)) / 2
  Next

  ET = QPF.GetMilliTime - ST

  Me.TextBox1.Text = ET.ToString("#,##0.000") '+ "ms"
End Sub

 と言う訳で、構造体に対応する演算子を作ったおかげで for ループ内の処理が大変簡単に書くことができました。

 シンプルな構造体宣言には演算子がありませんので、メンバ毎に同じ処理を書かなくてはならず、上記例のような簡単なものならたいしたことはないかも知れませんがもっと高度な演算をさせようとしたときに、演算子の宣言は威力を発揮すると思われます。

 もうお気づきのこととは思いますが、 GetMilliTime を使用していると言うことは処理時間を計っているのだろう?と言うことですね。 ソースに出てくる VOL は定数宣言で、1800万が宣言してあります。 構造体の要素はR,G,Bですから、何となく1800万画素の画像を処理するプログラムの一部ではないかと想像が付きますね。

 で、処理時間は、

シンプルな構造体 251ms
高度な構造体 668ms

 プログラムの動きを想像してみると、どうしてこのような差ができるのか想像できると思いますが、1800万回ものループ内で行われていることは、ソース3行と1行の違いではあるものの、オペレータ内では結局個々のメンバに対して演算しているので、呼出のオーバヘッドだけでもバカになりませんね。

 構造体の扱いとしては「高度な・・・」方が楽に決まっていますし、ソースもシンプルになるので思考の妨げにもなりにくいと思いますが、大きな画像を扱うような場合はその処理速度の遅さが致命的になることもあり得るという例です。(2013/01/04)

 

※上記サンプルプログラムは、テスト目的だけのために書き下ろしたものであって、実際の運用に耐えうるものではありません。 コピペしてお持ち帰りになるのはご自由に、ですが流用した結果に対する責任はご自身で持って下さい。