tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re: クラスの場合は・・
投稿日: 2007/09/11(Tue) 14:14
投稿者魔界の仮面弁士
あら。いつの間にか質問に書き換わっている…? (^^;

> 新たな文字が代入されれば「新たなインスタンス」が生成されるということではないのでしょうか。
その通りです。

Visual Basic の言語仕様においては、String 型のインスタンスを生成するには、
通常のクラスのように New を使ってインスタンスを生成するのではなく、
"〜" というリテラルを使って生成できるようになっているということです。


> とすればクラス、構造体のどちらのString型変数FirstNameも
> 新たに生成されるインスタンスを指し示すわけではないのですか・・・

下記のコメントで分かりますでしょうか。

'====== 構造体の中にある String メンバの場合 ======

Dim aPersonStruct1, aPersonStruct2 As PersonStruct
aPersonStruct1 = New PersonStruct()
aPersonStruct1.FirstName = "xyz"

'値型なので、値のコピーが渡される
aPersonStruct2 = aPersonStruct1

'コピー先も、同じ文字列インスタンスを参照しているので、True になる。
Console.WriteLine(aPersonStruct2.FirstName Is aPersonStruct1.FirstName)

'コピー元にだけ、別の文字列インスタンスを参照させる。
aPersonStruct1.FirstName = "XYZ"

'コピー元とコピー先で異なるインスタンスを指すため、False になる。
Console.WriteLine(aPersonStruct2.FirstName Is aPersonStruct1.FirstName)


'====== クラスの中にある String メンバの場合 ======

Dim aPersonClass1, aPersonClass2 As Person
aPersonClass1 = New Person()
aPersonClass1.FirstName = "abc"

'参照型なので、インスタンスはコピーされず、参照情報のみがコピーされる
aPersonClass2 = aPersonClass1

'両者は、同一の Person インスタンスを指すため、True になる。
Console.WriteLine(aPersonClass2 Is aPersonClass1)

'同じインスタンスなのだから、その中のメンバも当然同一であり、True になる。
Console.WriteLine(aPersonClass2.FirstName Is aPersonClass1.FirstName)

'その同一インスタンスの FirstName に、別の文字列インスタンスを参照させる。
aPersonClass1.FirstName = "ABC"

'両者が同一のインスタンスを指している事実は変わらないので、引き続き True のまま。
Console.WriteLine(aPersonClass2 Is aPersonClass1)

'同じインスタンスなのだから、その中のメンバに別のインスタンスを参照させた場合には、
'両者のメンバから見えるインスタンスも等しく書き換わるため、True となる。
Console.WriteLine(aPersonClass2.FirstName Is aPersonClass1.FirstName)

'=================================================


> そもそもFirstNameには「住所」みたいなものが格納されているとおもっているのですが・・
では、例え話にしてみましょうか。


文字列データの実態を『家』だと仮定しましょう。
その場合、String 変数とは、『住所が書れた紙』を意味します。
クラス内/構造体内の String 変数とは、『その紙が机の引出しに保存された状態』です。

String 型が不変であるという事は
 その紙に書かれた住所は消しゴムでは消せず、固定的であるということです。
Sring 変数に別の文字列を代入できるという事は、
 引き出し内の『紙』を、別のものに差し替える事ならばできるということです。


前提条件はここまで。
では、「参照情報のコピー」と「値のコピー」の違いについて見ていきましょう。


クラスのコピーすなわち
 aPersonClass2 = aPersonClass1
の場合、両者は『同じ机を眺めている状態』です。
同じ机なので、引き出しの中にある紙も同じであり、書かれている住所も同一です。
ゆえにコピー直後は、aPersonClass1.FirstName と aPersonClass2.FirstName は同一です。

ここで、別のインスタンスの代入、すなわち
 aPersonClass1.FirstName = "ABC"
の処理を行ったとしましょう。これは、引き出し内の『紙』を差し替えるという作業です。

aPersonClass1 さんが見ている机の引き出しを開いて、中の紙を別の紙に差し替えた場合、
aPersonClass2 さんが見ている机の引き出しの中にあった紙も、別のものに差し替わります。
(なぜならば、両者は同じ机を見ているのですから)
そのため、aPersonClass1.FirstName と aPersonClass2.FirstName は常に同じインスタンスです。


構造体のコピーすなわち
 aPersonStruct2 = aPersonStruct1
の場合、『その机の複製が生成された状態』です。
両者の机の中にある紙は別の紙ですが、書かれている住所は同じ家を指しています。
ゆえにコピー直後は、aPersonStruct1.FirstName と aPersonStruct2.FirstName は同一です。

ここで、別のインスタンスの代入、すなわち
 aPersonStruct1.FirstName = "XYZ"
の処理を行ったとしましょう。これは、引き出し内の『紙』を差し替えるという作業でしたね。

aPersonStruct1 さんが見ている机の引き出しを開いて、中の紙を別の紙に差し替えた場合でも、
aPersonStruct2 さんが見ている机の引き出しの中にあった紙は変化せず、元のままです。
(なぜならば、両者は、複製された異なる机を見ているからです)
そのため、aPersonStruct1.FirstName と aPersonStruct2.FirstName は異なるインスタンスになります。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。