VB.NETで変数として宣言できるデータ型は大きく分けて「値型」と「参照型」に分けられます。 「参照型」は、初めてVB.NETを使い始めた方にとっては、なかなか理解しにくい部分でもあります。 かく言う私もそのひとりではありますが。
「値型」は変数としてよく使う、Integer、Double、Decimal、DateTime及び構造体、列挙型などで、 「参照型」はクラス、配列などです。
「値型」のInteger、Doubleなどは直感的に分かりやすいのですが、 「参照型」の実際はどうなのか理解しにくいものです。
「値型」とは変数を保持しているメモリ上に直接データをアクセスできるもので、 「参照型」とはその変数に保持しているのは、参照型データの実体を指し示すポインタ的なものです。
言葉で説明すると何のことか分かりにくいので 「値型」と「参照型」を比較する為、構造体とクラスで説明します。
以下の様な構造体とクラスを宣言します。
このテスト用構造体を以下の様に使います。 このソースを適当なところで入力し、デバッグモードで1行ずつ実行させると分かりやすいです。
構造体のテストでは、1行目で構造体「ST1」の宣言をしていますが、この時点で「ST1」の実体がメモリに確保されます。 宣言の後で直接「ST1」のメンバ変数「nTest」に1を設定します。
その後で構造体「ST2」の宣言し、「ST2」に「ST1」を代入していますが、 「ST2」に割り当てられた実体に「ST1」の全てがまるまるコピーされます。
「ST2」と「ST1」の実体は全く別の独立したメモリ領域に存在していますので、 「ST2」のメンバ変数「nTest」に2を設定しても、「ST1.nTest」および「ST2.nTest」は異なる値を保持しています。
クラスのテストでは、1行目でクラス「CT1」の宣言をしていますが、この時点ではCT1には実体は設定しておらず、 値的には「Nothing」になっています。尚、値が「Nothing」である参照型の変数のメソッドやプロパティにアクセスしても エラーが発生します。
その後の「New」を行うことで、「ClassTest」の実体がメモリに確保され、その参照が「CT1」に代入されます。 参照とはメモリに確保された「ClassTest」の入れ物を指し示すポインタの様なものです。
この時点で「CT1」のメンバ変数にアクセスが可能になります。
クラスのテストでは、4行目でクラス「CT2」の宣言を行いますが、当然「CT2」の中身は「Nothing」のままです。 ここで5行目で「CT2」に「CT1」の値をコピーしています。 値のコピーと言っても、中身は「ClassTest」の実体メモリへの参照する値です。
(「ClassTest」の入れ物を指し示すポインタのコピー)
最後の行で「CT2」を使って「CT2.nTest」へ2を設定しています。 ここで「CT1」の値をデバッガ等でみますと「2」になっているはずです。 参照型を初めて見る方にとっては、おやと思うでしょうが、 「CT2」も「CT1」もメモリ上の同じ場所を指し示しているので、 「CT1.nTest」で見ても「CT2.nTest」で見ても同じ値になります。
尚、クラス宣言と実体生成を以下の様に記述できます。 「CT2」もNewで生成すれば、全く別のクラス領域を指し示すことになりますので、 「CT1.nTest」と「CT2.nTest」は別の値になります。
=====
2016/01/28:の時の情報
「値型」は変数としてよく使う、Integer、Double、Decimal、DateTime及び構造体、列挙型などで、 「参照型」はクラス、配列などです。
「値型」のInteger、Doubleなどは直感的に分かりやすいのですが、 「参照型」の実際はどうなのか理解しにくいものです。
「値型」とは変数を保持しているメモリ上に直接データをアクセスできるもので、 「参照型」とはその変数に保持しているのは、参照型データの実体を指し示すポインタ的なものです。
言葉で説明すると何のことか分かりにくいので 「値型」と「参照型」を比較する為、構造体とクラスで説明します。
以下の様な構造体とクラスを宣言します。
'テスト用構造体宣言 Structure StrucTest Public nTest As Integer 'Publicなメンバ変数 End Structure 'テスト用クラス宣言 Class ClassTest Public nTest As Integer 'Publicなメンバ変数 End Class
このテスト用構造体を以下の様に使います。 このソースを適当なところで入力し、デバッグモードで1行ずつ実行させると分かりやすいです。
'構造体のテスト Dim ST1 As StrucTest '構造体「ST1」の宣言 ST1.nTest = 1 'メンバ変数「nTest」に1を設定 Dim ST2 As StrucTest '構造体「ST2」の宣言 ST2 = ST1 '「ST1」の内容を「ST2」にコピー ST2.nTest = 2 'メンバ変数「nTest」に2を設定 'クラスのテスト Dim CT1 As ClassTest 'クラス「CT1」の宣言 CT1 = New ClassTest 'クラスの実体を生成し「CT1」に代入 CT1.nTest = 1 'メンバ変数「nTest」に1を設定 Dim CT2 As ClassTest 'クラス「ST2」の宣言 CT2 = CT1 '「CT1」の内容を「CT2」にコピー CT2.nTest = 2 'メンバ変数「nTest」に2を設定
構造体のテストでは、1行目で構造体「ST1」の宣言をしていますが、この時点で「ST1」の実体がメモリに確保されます。 宣言の後で直接「ST1」のメンバ変数「nTest」に1を設定します。
その後で構造体「ST2」の宣言し、「ST2」に「ST1」を代入していますが、 「ST2」に割り当てられた実体に「ST1」の全てがまるまるコピーされます。
「ST2」と「ST1」の実体は全く別の独立したメモリ領域に存在していますので、 「ST2」のメンバ変数「nTest」に2を設定しても、「ST1.nTest」および「ST2.nTest」は異なる値を保持しています。
クラスのテストでは、1行目でクラス「CT1」の宣言をしていますが、この時点ではCT1には実体は設定しておらず、 値的には「Nothing」になっています。尚、値が「Nothing」である参照型の変数のメソッドやプロパティにアクセスしても エラーが発生します。
その後の「New」を行うことで、「ClassTest」の実体がメモリに確保され、その参照が「CT1」に代入されます。 参照とはメモリに確保された「ClassTest」の入れ物を指し示すポインタの様なものです。
この時点で「CT1」のメンバ変数にアクセスが可能になります。
クラスのテストでは、4行目でクラス「CT2」の宣言を行いますが、当然「CT2」の中身は「Nothing」のままです。 ここで5行目で「CT2」に「CT1」の値をコピーしています。 値のコピーと言っても、中身は「ClassTest」の実体メモリへの参照する値です。
(「ClassTest」の入れ物を指し示すポインタのコピー)
最後の行で「CT2」を使って「CT2.nTest」へ2を設定しています。 ここで「CT1」の値をデバッガ等でみますと「2」になっているはずです。 参照型を初めて見る方にとっては、おやと思うでしょうが、 「CT2」も「CT1」もメモリ上の同じ場所を指し示しているので、 「CT1.nTest」で見ても「CT2.nTest」で見ても同じ値になります。
尚、クラス宣言と実体生成を以下の様に記述できます。 「CT2」もNewで生成すれば、全く別のクラス領域を指し示すことになりますので、 「CT1.nTest」と「CT2.nTest」は別の値になります。
'クラスのテスト2 Dim CT1 As New ClassTest 'クラス「CT1」の実体を生成し「CT1」に代入 CT1.nTest = 1 'メンバ変数「nTest」に1を設定 Dim CT2 As New ClassTest 'クラス「CT2」の実体を生成し「CT2」に代入 CT2.nTest = 2 'メンバ変数「nTest」に2を設定
=====
2016/01/28:の時の情報
PR
コメント