連載

プロフェッショナルVB.NETプログラミング

第28回 属性(前編)

(株)ピーデー
川俣 晶
2002/12/07

Page1 Page2 Page3

オブジェクトのシリアライズ

 オブジェクトを外部へ出力するために「シリアライズ」という機能が用意されることが多い。シリアライズは、特定の機能を示す言葉ではなく、世の中には、さまざまな方法でシリアライズを行うライブラリが存在する。VB.NETでは、あるクラスがシリアライズ可能であることを示すために、属性を用いて指定する方法が取られている。シリアライズはクラス・ライブラリが提供する機能であり、VB.NET独自の機能というわけではない。そのため、本連載では大きく取り上げないが、属性の利用例として属性がどのように使われているかを見てみよう。以下のようなサンプル・プログラムを用意してみた。

  1: Imports System.IO
  2: Imports System.Runtime.Serialization
  3: Imports System.Runtime.Serialization.Formatters.Binary
  4:
  5: Public Class Form1
  6:   Inherits System.Windows.Forms.Form
  7:
  8: …Windows フォーム デザイナで生成されたコード…
  9:
 10:   <Serializable()> Private Class Person
 11:     Public Age As Integer
 12:     Public Name As String
 13:     <NonSerialized()> Public Flag As Boolean
 14:   End Class
 15:
 16:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
 17:     Dim p1 As New Person()
 18:     p1.Age = 17
 19:     p1.Name = "山田太郎"
 20:     p1.Flag = True
 21:
 22:     Dim formatter As New BinaryFormatter()
 23:     Dim outputStream As New FileStream("c:\test.dat", FileMode.Create)
 24:     Try
 25:       formatter.Serialize(outputStream, p1)
 26:     Finally
 27:       outputStream.Close()
 28:     End Try
 29:
 30:     Dim p2 As Person
 31:     Dim inputStream As New FileStream("c:\test.dat", FileMode.Open)
 32:     Try
 33:       p2 = CType(formatter.Deserialize(inputStream), Person)
 34:     Finally
 35:       inputStream.Close()
 36:     End Try
 37:
 38:     Trace.WriteLine(p2.Age)
 39:     Trace.WriteLine(p2.Name)
 40:     Trace.WriteLine(p2.Flag)
 41:   End Sub
 42: End Class
オブジェクトのシリアライズのためにSerializable属性を使用したサンプル・プログラム3

 これを実行すると以下のような結果になる。

 1: 17
 2: 山田太郎
 3: False
サンプル・プログラム3の実行結果

 このソースで最も注目すべき点は、10行目のクラス宣言に付加されたSerializable属性である。この属性が付加されていることにより、Personクラスはシリアライズできると判断される。では、だれがその判断を行うのかというと、22行目で使用されているBinaryFormatterクラスである。このクラスは、バイナリ形式でシリアライズを行う機能を持っている。25行目のように、このクラスのインスタンスのSerializeメソッドを使うことにより、シリアライズ可能なインスタンスの内容を指定ストリームに書き込むことができる。これにより、インスタンスの内容がファイルの中に記憶される。

 次に注目する価値があるのは、13行目のNonSerialized属性である。この属性は、クラスではなくフィールドに付く。そして、そのフィールドがシリアライズの対象ではないことを指定する。これにより、Public Flag As Booleanはシリアライズの対象から除外され、20行目で代入した値はファイルに保存されない。実行結果を見ると、Flagの値のみ代入した値が再現されていないことが分かるだろう。属性には、こういう指定に使う方法もある。

 さて、このほかに説明を要する点は33行目だろう。DeserializeメソッドはSerializeメソッドの逆、つまりSerializeメソッドで書き出されたデータからオブジェクトを作成する機能を持っている。DeserializeメソッドはObject型を返すため、元の型に戻すためにCType関数を使用している。

属性の名前のバリエーション

 ここまでの説明を読んで、「あれ?」と思った読者もいるのではないだろうか。というのは、VBFixedStringAttribute属性を、VBFixedString属性と記述している資料も存在するからである。さらに、名前空間を明示した名前を記述しても、エラーにならない。以下のサンプル・プログラムは、Serializableを例にして、これらのバリエーションを並べて書いてみたものである。

  1:   <Serializable()> Private Class Sample1
  2:     Public a As Integer
  3:     Public b As Integer
  4:   End Class
  5:
  6:   <SerializableAttribute()> Private Class Sample2
  7:     Public a As Integer
  8:     Public b As Integer
  9:   End Class
 10:
 11:   <System.SerializableAttribute()> Private Class Sample3
 12:     Public a As Integer
 13:     Public b As Integer
 14:   End Class
属性を記述する場合の3つバリエーション

 このサンプル・プログラムで示した3つのクラスは、まったく同じ内容を定義していることになる。これらのクラスに付いた属性名、Serializable、SerializableAttribute、System.SerializableAttributeは、すべて同じものを示している。これは2つの事実を知ることで容易に理解することができる。

 第1の事実は、属性の実体はクラスであるということだ。そのため、記述方法もクラスと何ら変わることはなく、System.SerializableAttributeとフルネームで書いてもよく、省略可能な名前空間名を省略して、SerializableAttributeと書いてもよい。また、Imports文でデフォルトの名前空間名を指定すれば、属性の名前空間名の部分を省略して書くこともできる。属性の機能について調べたいときも、クラス・ライブラリのリファレンスを開き、クラス名として属性名を調べることで、必要な情報を得ることができる。

 第2の事実は、属性を実現しているクラスの名前は、必ずAttributeという文字列で終わり、この文字列は属性としてソース・コードに記述する際に省略可能ということである。つまり、SerializableAttributeという属性名を記述する際、最後の“Attribute”を省略して、Serializableとだけ書いてもよいということである。この機能により、VBFixedStringAttributeとVBFixedStringはどちらの名前を使っても結果は同じである。また、リファレンス・マニュアルを引くときに、VBFixedStringというキーワードでは出てこない場合があったとしても、それに省略された文字列Attributeを補い、VBFixedStringAttributeというキーワードで引いてみるというテクニックも可能である。しかし、この省略は属性として記述する場合にのみ有効なものであり、クラス名として記述する場合はAttributeという文字列を省略できない。

 なお、リファレンス・マニュアルで、VBFixedStringAttributeを引いても、これが属する名前空間が明記されていないが、オブジェクト・ブラウザで見ればすぐに分かる。VBFixedStringAttribute属性の名前空間は、Microsoft.Visual Basicである。つまり、そのフルネームは、Microsoft.Visual Basic.VBFixedStringAttributeとなる。

オブジェクト・ブラウザで表示させたVBFixedStringAttribute属性(VBFixedStringAttributeクラス)
 

 INDEX
  連載 プロフェッショナルVB.NETプログラミング
  第28回 属性(前編)
    1.属性とは何か?
  2.オブジェクトのシリアライズ
    3.Declare文の引数型を変換するMarshalAs属性
 
「プロフェッショナルVB.NETプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間