Visual Basic 初級講座
VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

 

Visual Basic 中学校 > 初級講座 >

第32回 属性

属性は地味で、必要不可欠でもありません。そして、その独特な構文や効果などは紛れもなくVBでのプログラムにおいて1つの要素を構成しています。今回の説明で、みなさんが属性が適用されているプログラムを読む手助けになれば幸いです。

この回の要約

・ 属性を使用すると変数やメソッド、クラス、アプリケーションなどに追加情報を記述することができる。

・属性は < > を使って次のように記述する。

    <VBFixedString(10)> Dim Item1 As String

・属性には何の機能もない。

・属性を使用してプログラムの会社名やバージョンを記述することができる。

・属性を使用して固定長テキストファイルを作成することができる。

 

1.属性とは

 

属性とは変数やメソッドに特別な情報を記録する仕組みのことです。たとえば、メソッドとはその宣言と記述されたプログラムのみから構成されるのが普通ですが、属性を使用することでさらに情報を与えることができます。たとえば、メソッドの作成者の名前や作成日時を記録することができます。

属性はあらかじめVBに用意されているものもたくさんありますが、自分で作成することもできます。今回はあらかじめ用意されている属性を利用する方法だけを説明します。

はじめての方はイメージがわかないと思いますのでまず属性を利用したサンプルを紹介します。次の例ではメソッドに説明を追加します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

<System.ComponentModel.Description("このメソッドはテスト用です。")> _
Private Sub MyMethod()

    MsgBox("テストです!")

End Sub

■リスト1:属性の適用

この例を見ていただければわかるように、属性を付加する場合は < > で囲むという特別な記述方法が必要です。また、この例では説明を付加していますが、属性自体には何の機能もないことに注意してください。

どの属性にも何の機能もありません。単に追加的な情報を記録しておくだけです。それにこの記録しておいた情報を見る場所もありません。(プログラムを開けば見えますが…)。

では、なぜ属性を使用するのか?属性を利用して具体的にどのような便利なことが起きるのかこれから順を追って説明しましょう。

 

2.属性の対象

 

属性は追加的な情報なのですから、属性を付加する対象がなければなりません。属性を付加できる対象には次のようなものがあります。

変数
クラスや構造体のメンバ
クラスや構造体
アセンブリやモジュール

属性は属性ごとに何を対象とするのか決まっています。たとえば、変数用の属性をクラスに適用することはできません。ただし、クラスにも変数にも適用できる属性というものも存在します。

次に変数に属性を適用する例を示します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応


<System.ComponentModel.Description("変数です。")> Dim Value As String
 

■リスト2:変数への属性の適用

メソッドに属性を適用する例を示します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    components = New System.ComponentModel.Container
   
Me.Text = "Form1"

End Sub

■リスト3:メソッドへの属性の適用

メソッドに属性を適用するとメソッドの宣言が長くなり読みにくいので行継続文字を使って次のように記述するプログラマが多いようです。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()

    components = New System.ComponentModel.Container
   
Me.Text = "Form1"

End Sub

■リスト4:行継続文字の使用

このDebuggerStepThrough属性(読み方:DebuggerStepThrough = デバッガステップスルー)はメソッドの機能には何の影響もありません。ただし、デバッガはこの属性のあるメソッドではステップイン実行を行いません。デバッガやステップイン実行については初級講座のもう少し後の回で説明します。このように属性とはプログラムの機能には何の影響もないのですが、ある種の目印として使用されることがあります。

クラスに属性を適用する例を示します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

<System.ComponentModel.Description("テストクラス")> _
Public Class TestClass

End Class

■リスト5:クラスへの属性の適用

最後にアセンブリやモジュールに属性を適用する例を示します。「アセンブリ」や「モジュール」という言葉は初級講座の現在の段階では聞きなれない言葉だと思いますが、とりあえず「アプリケーション」とか「プログラム」という程度の意味だと思っておいてください。

もちろん、これは便宜上の説明で真実の意味とは異なります。「アセンブリ」という言葉についてはっきりと知りたい方はMSDNライブラリを参照してください。丁寧に説明してあります。

さて、アセンブリに属性を適用する方法は今までとは少し違って、キーワードAssembly(読み方:Assembly = アセンブリ)を使用します。次のようになります。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応


<Assembly: System.Reflection.AssemblyCompany("Visual Basic 中学校")>
 

■リスト6:アセンブリへの属性の適用

この属性とその効果については節を改めて説明します。

 

3.属性の効果

 

AssemblyCompany属性(読み方:AssemblyCompany = アセンブリカンパニー)はあなたのプログラムに会社名情報を付加します。

この属性はSystem.Reflection名前空間(読み方:Reflection = リフレクション)に属しているため、完全限定名で指定するとき(つまり、いきなり使用するとき)にはSystem.Reflection.AssemblyCompanyと記述する必要があります。

しかし、この記述はちょっと長すぎるので以下の説明ではSystem.Refrection名前空間をImportsに指定して省略可能にしています。

この属性の効果を試すためにForm1の先頭に次のように記述してください。ただしVB2005の場合はこの記述はエラーになります。本質的にはVB2005でもここの説明があてはまるのですが、VBによるチェック機能が強化されているために失敗するようです。VB2005を使用している場合は実際に試すことはできませんがこのまま読み進めてください。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Imports System.Reflection

<Assembly: AssemblyCompany("Visual Basic 中学校")>

■リスト7:会社名

この状態でプログラムを実行してみてください。何もプログラムしていなくても構いません。実行すると何も特別な変化がないことがわかります。属性には何の機能もないのですから当然です。それでは設定した会社名「Visual Basic 中学校」はどこにいったのか確認してみましょう。

プロジェクトを保存したフォルダを開いてBinフォルダの中を開けてください。この中にあなたが今作成したexeファイルがありますから、そのexeファイルを右クリックしてプロパティを選択してください。そして[バージョン情報]タブの「会社名」をクリックすると見事に「Visual Basic 中学校」という情報が記述されているのがわかります。

■画像1:会社名

会社名情報はプログラムで取り出すこともできます。次のようにプログラムするとAssemblyCompany属性で指定した会社名が表示されます。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応


MsgBox(Application.CompanyName)
 

■リスト8:会社名の表示

このように手軽に使えるアセンブリ用の属性は他にもいくつか用意されています。下に表にして紹介しますがこれらはどれも会社名情報と同じような効果を発揮します。

属性 読み方 意味
AssemblyCompany アセンブリカンパニー 会社名
AssemblyProduct アセンブリプロダクト 製品名
AssemblyTrademark アセンブリトレードマーク 商標
AssemblyCopyright アセンブリコピーライト 著作権
AssemblyVersion アセンブリバージョン バージョン
AssemblyFileVersion アセンブリファイルバージョン ファイルバージョン
AssemblyTitle アセンブリタイトル タイトル
AssemblyDescription アセンブリデスクリプション 説明

この中でAssemblyVersion属性だけは他と違う特別で重要な効果がありますが、この効果を簡単に説明することはできませんので別の機会に説明します。MSDNライブラリやインターネット等を使って調べたい方は「厳密名」をキーワードに検索してみてください。

さて、これらの属性ですが本格的なソフトを製作するのでしたらどれもちゃんとした値を設定しておいた方が良さそうな項目ですよね。そこでVBはこれらの属性は特別にすぐに値を設定できるように準備しておいてくれています。

VB.NET2002またはVB.NET2003を使用している場合はあなたのプロジェクトにAssemblyInfo.vbというファイルがあるはずですからこのファイルを開いて中身を見てください。

■画像2:AssemblyInfo.vb

見るとすぐ分かるのですが、これらの属性がもう用意されていていつでも値を書き込むだけという状態になっています。ですから通常はこれらの属性は自分で宣言しないでAssemblyInfo.vbファイルを利用するようにしましょう。

VB2005を使用している場合でもAssemblyInfo.vbファイルに同様の記述があるのですがこのファイルは既定の設定では画されています。その代わりMy Projectの[アプリケーション]タブにある[アセンブリ情報]ボタンをクリックすると専用のダイアログが開いてここで値を設定することができます。VB2005は現時点ではまだ製品版が発売されていませんから、製品版発売時にはこのダイアログの内容や表示情報が変更されている可能性がありますから注意してください。

 

4.固定長テキスト

 

次に属性の設定がプログラムの動作に影響する例を紹介します。固定長テキストファイルの書き込みです。

固定長テキストファイルとは項目を固定幅で書き表すテキストファイルのことです。たとえば、名前は10バイト、電話番号は13バイト、性別は2バイトという設定では固定長テキストファイルは次のようになります。

山田太郎  090-1122-3344男
山田花    03-1122-3344 女

既定のバイト数に達するようにデータのない部分にスペース等が埋め込まれるのが特徴です。もし、バイト数を気にしないで単にデータを順番に書き込んでいくと次のようになってしまいます。

山田太郎090-1122-3344男
山田花03-1122-3344女

これではたとえば電話番号を取得するプログラムを書くのは大変です。固定長テキストであれば電話番号は必ず11バイト目から13バイト分の長さで書き込まれているので簡単に取得することができます。

ただ、属性を使って固定長テキストファイルを作成する例を紹介するためにはまだ説明していない方法でのファイルの書き込みの知識が必要です。細部にはあまりとらわれずにざっと読み流す形で属性の効果についてだけ理解していただければ幸いです。

まず、属性を使用しない形でのプログラム例を紹介します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Private Structure TextLine
    Dim Item1 As
String
   
Dim Item2 As String
    Dim Item3 As String
End Structure

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim Line As TextLine

    Line.Item1 = "山田花"
   
Line.Item2 = "03-1122-3344"
   
Line.Item3 = "女"

    FileOpen(1, "C:\FixedText.txt", OpenMode.Random)
    FilePut(1, Line)
    FileClose(1)

End Sub

■リスト9:旧式な方法でのファイルへの書き込み。

この例では、当然テキストファイルは固定長になりません。どこにも項目の幅を指定する部分がないのですぐにお分かりと思います。

念のために書き込まれたテキストを見てみると確かにそれらしいデータは書き込まれているのですがなにやらわけのわからない文字も一緒に書き込まれているのが確認できます。

発展学習  -  変数の構造

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

上記の例で作成されるテキストファイルは明らかにプログラマの意図したものではありませんが、それでもでたらめというわけではありません。このファイルにはString型の持っている「値」とともに「構造上のデータ」が書き込まれてしまっているのです。

このテキストファイルをバイナリエディタで開いてみればそれぞれの値の前に2バイト分の余分な情報が付加されていることがわかります。そして、この「余分な情報」をよく見ると値の文字数と一致していることがわかります。

次にこの例に属性を適用して固定長テキストを作成する例を紹介します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

Private Structure TextLine
<VBFixedString(10)> Dim Item1 As
String
<VBFixedString(13)> Dim Item2 As String
<VBFixedString(2)> Dim Item3 As String
End Structure

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim Line As TextLine

    Line.Item1 = "山田花"
   
Line.Item2 = "03-1122-3344"
   
Line.Item3 = "女"

    FileOpen(1, "C:\FixedText.txt", OpenMode.Random)
    FilePut(1, Line)
    FileClose(1)

End Sub

■リスト10:旧式な方法での固定長テキストファイルへの書き込み

TextLine構造体の各変数に固定幅情報を表すVBFixedString属性(読み方:VBFixedString = ブイビーフィックスドストリング)を付加しただけですが、結果は見事に固定長テキストファイルの作成に成功します。

このVBFixedString属性は属性が結果に大きな影響を与えるかなり珍しい例です。はじめに「属性には何の機能もありません」と書いたことと結果的には矛盾しています。

実はこのからくりはFilePut関数(読み方:FilePut = ファイルプット)にあります。この関数は固定長でのテキストファイルの書き込みにあらかじめ対応していて、書き込む構造体にVBFixedString属性が適用されているかどうか検査を行っているのです。

このように関数やメソッド自体が属性の検査を行って属性によって異なる処理を実行するようにプログラムされている場合は本来何の機能もないはずの属性があたかも何かの機能があるかのように結果に影響を与えることがあるのです。

ところで、この例で登場したFilePutなどを使用したファイルの書き込みは旧式のものです。VB6との互換性のために残されている機能なので新しくVB.NETを勉強する場合には特に利用しないことをお勧めします。ファイルの書き込みには前々回紹介したStreamWriterクラスを使用するようにしましょう。

とはいえ、StremWriterクラスは固定長テキストファイルの書き込みをサポートしていませんから、自分で幅をそろえるようにプログラムする必要があります。それが面倒だという方は上記の例の様にFilePutを使ってもよいでしょう。

 

5.属性の正体

 

さて、今までいくつかの属性を紹介してきました。属性とはどのようなものなのかおおよそ理解していただけたと思います。

属性は < > といった特別な記述方法を使用するところから特別に用意された要素のように感じられるかもしれませんが実は属性の正体は「クラス」なのです。

ですから、ヘルプ等でそれぞれの属性を調べるときはやはりクラスを探すことになります。そして、属性クラスの特徴は名前の最後が必ずAttribute(読み方:Attribute = アトリビュート)となっていることです。

たとえば、今回登場したDescription属性のクラス名はDescriptionAttributeとなります。このように属性として使用する場合は特別に末尾のAttributeを省略することができるのです。しかし、MSDNライブラリ等では正式名称のDescriptionAttributeとして掲載されていますので注意してください。

 

ところで、この「属性」ですがあまりこった使い方をするとプログラムが複雑になってしまいます。特に自作の属性をつかっていろいろな機能を実現しようとするとプログラムの可読性が低下します。今回最後に紹介したVBFixedString属性も属性が関数の効果に影響を与える点がとてもわかりにくいと私には感じられます。もっともVBFixedString属性はVB6との互換性のために特別に用意された属性ですからまだ納得はできます。

しかし、メソッドの機能に直接影響を与える属性がそこかしこに存在するようだとプログラムが煩雑になってしまうことは容易に想像できます。

みなさんには、あらかじめ用意されている属性を必要最小限につかっていく程度のスタンスをお勧めしたいと思います。

このスタンスでも自分でコントロールやクラスを作成するようになるといろいろな属性を使用するようになります。

説明が後手になってしまいましたが1つの要素に複数の属性を付加するには , を使用することを最後に紹介しておきます。

次の例ではメソッドにDescription属性とDebuggerStepThrough属性を付加します。

VB.NET 2002 対応 VB.NET 2003 対応 VB2005 対応

<System.ComponentModel.Description("テスト"), System.Diagnostics.DebuggerStepThrough()> _
Private Function MyMethod() As
Integer

End Function

■リスト11:2つの属性の適用