■ 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
Public Sub Clear()
R = 0
G = 0
B = 0
End Sub
Public Function Brightness() As Single
Return CSng((R + G + B) * (1 / 3))
End Function
Public Function GrayScale() As Byte
Return CByte(Fix(R * BRK + G * BGK + B * BBK))
End Function
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
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)
|