VB のたまご

作成日: 2015/12/03, 更新日: 2015/12/03


値渡しと参照渡しの違いを知って、引数の扱いをマスターしよう

  •  この記事内では、値型と参照型について、すでに理解しているものとして説明をしています。
  • まだ読まれていない方は、先にこちらをご覧ください。
  • 不要な方は、このままご覧ください。

値型データで見る、値渡しと参照渡し

  •  まずは動作結果を見てみましょう。
  • Dim age As Integer = 15
    Me.S1(age)
    Console.WriteLine(", age = {0}", age)
    Me.S2(age)
    Console.WriteLine(", age = {0}", age)
            
    Private Sub S1(ByVal value As Integer)
        value += 1
        Console.Write("value = {0}", value)
    End Sub
    
    Private Sub S2(ByRef value As Integer)
        value += 1
        Console.Write("value = {0}", value)
    End Sub
    
    ' 出力結果
    value = 16, age = 15
    value = 16, age = 16
    

  •  値渡し(ByVal)の方は、メソッド内で変数の値を変更しても、呼び出し元で渡した変数には影響していません。 しかし、参照渡し(ByRef)の方は、呼び出し元で渡した変数の値も変わってしまいました。引数を渡す際に、 渡す変数自体にも影響するかしないかを制御できるのですね。

スポンサーリンク


参照型データで見る、値渡しと参照渡し

  •  続いて、参照型データを渡して、動作結果を見てみましょう。
  • Dim frm As New Form With {.Name = "form1"}
    Me.S1(frm)
    Console.WriteLine(", frm.Name = {0}", frm.Name)
    Me.S2(frm)
    Console.WriteLine(", frm.Name = {0}", frm.Name)
            
    Private Sub S1(ByVal value As Form)
        value.Name = "s1 メソッドからセット"
        Console.Write("value = {0}", value.Name)
    End Sub
    
    Private Sub S2(ByRef value As Form)
        value.Name = "s2 メソッドからセット"
        Console.Write("value = {0}", value.Name)
    End Sub
    
    ' 出力結果
    value = s1 メソッドからセット, frm.Name = s1 メソッドからセット
    value = s2 メソッドからセット, frm.Name = s2 メソッドからセット
    

  •  値渡し(ByVal)も参照渡し(ByRef)も、呼び出し元で渡した変数の値が変わってしまいました。
  • 先程の、値型データかつ参照渡しのパターンでは、参照渡しが優先されて、渡した変数の値が変わりましたね。 そして、参照型データかつ値渡しのパターンでは、参照型データが優先されて、渡した変数の値が変わりました。

  • パターン別結果
    型のタイプ 渡す方法 結果
    値型 値渡し 渡した変数に、影響無し
    値型 参照渡し 渡した変数に、影響あり
    参照型 値渡し 渡した変数に、影響あり
    参照型 参照渡し 渡した変数に、影響あり


  •  つまり、値型の値渡し以外の場合、渡した変数が更新される可能性があるよ、という前提で捉えておくと良さそうです。

スポンサーリンク


参照型データの値渡しにおける限界と、参照型データの参照渡しの機能

  •  参照型データは、インスタンス生成すると新しい場所に準備して「新しい目印」をセットすると、前回の記事で分かりました。 ということは、次の場合はどうなるのでしょうか?
  • Dim frm As New Form With {.Name = "form1"}
    Me.S1(frm)
    Console.WriteLine(", frm.Name = {0}", frm.Name)
    Me.S2(frm)
    Console.WriteLine(", frm.Name = {0}", frm.Name)
            
    Private Sub S1(ByVal value As Form)
        value.Name = "s1 メソッドからセット"
        value = New Form With {.Name = "s1"}
        Console.Write("value = {0}", value.Name)
    End Sub
    
    Private Sub S2(ByRef value As Form)
        value.Name = "s2 メソッドからセット"
        value = New Form With {.Name = "s2"}
        Console.Write("value = {0}", value.Name)
    End Sub
    
    ' 出力結果
    value = s1, frm.Name = s1 メソッドからセット
    value = s2, frm.Name = s2
    

  •  参照型データの値渡しの場合、変数メンバー値の変更は、渡した変数側にも効いていますが、 その後のインスタンス生成した値は、渡した変数側には伝わっていません。 これは、「値渡し」の能力を超えた事だからです。値渡しでは、変数のメンバー値を変更することはできても、 変数「自体」のインスタンスを変更することはできません。変数「自体」のインスタンスを変更できるのが、 参照渡しです。

  •  最後までこの記事を読んでいただき、ありがとうございました。

  • スポンサーリンク