投稿までの経緯
いまのいままで参照渡しと値渡しの使いわけをしらず、取り敢えず値渡しをしていたため、調べてみた
#前提として値型と参照型とは??
値型・・・データそのものを格納できるデータ型 (構造体、列挙体)
参照型・・・データがあるアドレスを格納できるデータ型 (クラス、配列、インターフェイス、デリゲート)
具体例
値型・・・IntegerやDouble
参照型・・・Formやコントロール
ちなみに、アドレスが格納されている場所にもアドレスが割りたてられていることは忘れずに
動作的な違い
変数へ代入する際
値型・・・データを代入する
参照型・・・アドレスを代入する
つまり、参照型はアドレスの代入になるため、データを変更するとそのほかの参照している変数のデータも変わる
注意点
String型について
String型の場合はクラスになるので参照型だが、データの変更はできなく、変更する場合は新しくオブジェクトが作成される。
作成されず作成したい場合はStringBuilderクラスが良いらしい
#値渡しと参照渡し
関数を呼びだす際の引数の渡しかたの種類
値渡し・・・データのコピーを渡す
参照渡し・・・データのアドレスを渡す
ここで気になったのは
①値型×値渡し
②値型×参照渡し
③参照型×値渡し
④参照方×参照渡し
この4通りの動作にどういった違いがあるのかが気になった
#①値型×値渡し
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim intTest As Integer 'integer型(値型)
intTest = 255
Call SetIntValue(intTest)
Console.WriteLine("intは" & CStr(intTest))
End Sub
Private Sub SetIntValue(ByVal intTest As Integer)
intTest = 500
End Sub
intは255
この場合は値型の値渡しのなので、値のコピーが渡される。
それが呼び出し先で変更されただけで呼び出し元の値には変更されたので、出力結果のようになる
#②値型×参照渡し
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim intTest As Integer 'integer型(値型)
intTest = 255
Call SetIntValue(intTest)
Console.WriteLine("intは" & CStr(intTest))
End Sub
Private Sub SetIntValue(ByRef intTest As Integer)
intTest = 500
End Sub
intは500
この場合は参照渡しのなので、値型の値が格納されている『アドレス』が渡される。
この時点で、参照先と元で同じ値を参照していることになる。
その後、呼び出し先で値が変更されたので、出力結果のようになった。
#③参照型×値渡し
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim penTest As New Pen(Color.Aqua, 10) 'Penクラス(参照型)
Call SetPen(penTest)
Console.WriteLine("Penは" & CStr(penTest.Width))
End Sub
Private Sub SetPen(ByVal targetPen As Pen)
Dim convPen As New Pen(Color.Azure, 20)
targetPen.Width = 50
'以下のコードがあると呼び出し先のみ参照先が変更される
'targetPen = convPen
End Sub
Penは50
この場合は参照型の値渡しなので、参照型が格納している『参照している値のアドレス』が渡される。
この時点で、参照先と元で同じ値を参照していることになる。
その後、呼び出し先で値が変更されたので、出力結果のようになった。(②と結果的には同じ)
しかし、コメントの部分のように呼び出し先で新しく参照型を代入する場合は、呼び出し先のみ参照先が
変わってしまう。
#④参照型×参照渡し
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim penTest As New Pen(Color.Aqua, 10) 'Penクラス(参照型)
Call SetPen(penTest)
Console.WriteLine("Penは" & CStr(penTest.Width))
End Sub
Private Sub SetPen(ByRef targetPen As Pen)
Dim convPen As New Pen(Color.Azure, 20)
targetPen.Width = 50
'targetPen = convPen
End Sub
Penは50
この場合は参照型の参照渡しなので、厳密にいうと、参照型が格納している『参照している値のアドレス』のアドレスが渡される。
この時点で、参照先と元で同じ値を参照していることになる。
その後、呼び出し先で値が変更されたので、出力結果のようになった。
また、コメントの部分のように呼び出し先で新しく参照型を代入する場合は、『参照先の値のアドレス』が変更されるので、その『参照先の値のアドレス』のアドレスを参照している呼び出し元も変更される(アドレスのアドレスがわかりづらい笑)
#String型について
String型は特殊です。まず、型としてはStringクラスになるので参照型(char型の配列だから??)になります。しかし、処理としては参照先のデータを内容変更する際には新しくデータを生成し、そこを参照先に変更させているそうです。
参照記事
例
この例は参照型である、文字列を値渡し、呼び出し先で変更した場合です。この場合は上の内容でいうと呼びだし元も変更されるように思いますが、変更されません。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strTest As String '文字列(参照型)
Call SetStringValue(strTest)
Console.WriteLine("stringは" & strTest)
End Sub
Private Sub SetStringValue(ByVal strTest As String)
strTest = "サブプロシージャだよ~"
End Sub
stringはメインプロシージャだよ~
文字列の代入はオブジェクトの代入ととらえると理解しやすい
#処理速度について
データの値のコピーをする値渡しはデータが大きいものになると処理が遅くなる傾向があるらしい