[ VB.NET入門編 ] Sub Function プロシージャと引数 ( ByVal / ByRef )

Pocket

プロシージャと呼ばれるものの中で、ここでは Sub プロシージャと Function プロシージャについて、基本的なサンプルを例に出しながら掲載しています。Sub や Function 以外には、プロパティ ( Property ) や Operator などもプロシージャと呼ばれますが、ここでは取り上げていません。

スポンサーリンク

Sub, Fnction プロシージャのサンプル

簡単な例として足し算を行う Sub および Function プロシージャをそれぞれ作成し実行してみます。

   ' 足し算を行う Sub プロシージャ―定義
    Public Sub AddSub(ByVal p1 As Integer, ByVal p2 As Integer, ByRef sum As Integer)
        sum = p1 + p2
    End Sub

    ' 足し算を行う Function プロシージャ―定義
    Public Function AddFunction(ByVal p1 As Integer, ByVal p2 As Integer) As Integer
        Return (p1 + p2)
    End Function
    
    ' ------------------------------------------------------------
    ' 呼び出し元のコード
    ' ------------------------------------------------------------
    Dim sum As Integer = 0

    ' Subプロシージャ―の呼び出し
    AddSub(2, 3, sum)
    Console.WriteLine("AddSub 2 + 3 = " + sum.ToString())

    ' Functionプロシージャ―の呼び出し
    sum = AddFunction(2, 3)
    Console.WriteLine("AddFunction 2 + 3 = " + sum.ToString())

    '結果
    'AddSub 2 + 3 = 5
    'AddFunction 2 + 3 = 5

Sub と Function プロシージャの違い

Sub と Function プロシージャの違いは、サンプルコードからもわかるようにプロシージャの型を定義してリターン値を返すことができるものが Function、パラメータでの受け渡ししかできないものが Sub プロシージャです。次に、パラメータ定義部分で ByVal と ByRef キーワードがありますが、その違いは下表のようになります。

ByVal 呼び出し元で与えたパラメータのコピーがプロシージャに渡されます。プロシージャ内でパラメータ変数の値を上書きしても、呼び出し元の変数の値には影響を与えません。
ByRef 呼び出し元で与えたパラメータの参照がプロシージャに渡されます。プロシージャ内でパラメータ変数の値を上書きした場合、呼び出し元の変数の値も更新されます。

上記のサンプルでは、Sub プロシージャの足し算の結果を入れるパラメータ は (ByRef sum As Integer ) のように Byref で定義されています。プロシージャ呼び出し時は sum 変数の値は 0 ですが、呼出し後には、5 となっています。

次は、ByVal ByRef それぞれで定義した引数にクラスオブジェクトをパラメータに与えたときの違いをみてみます。

    'パラメータで使用するクラスオブジェクト
    Public Class ParamClass
        Public value As Integer
    End Class
    
    ' プロシージャ―
    Sub func(ByVal p1 As ParamClass, ByRef p2 As ParamClass)
        p1.value = 5

        p2 = New ParamClass()
        p2.value = 5

    End Sub

    ' ------------------------------------------------------------
    ' 呼び出し元のコード
    ' ------------------------------------------------------------
    Dim p1 As New ParamClass() 'インスタンス生成している
    Dim p2 As ParamClass       'プロシージャ―で生成したインスタンスの参照用
    p1.value = 0
    p2 = Nothing

    func(p1, p2)

    ' 呼び出し元でもvalueの値は上書きされている
    Console.WriteLine(p1.value.ToString())

    ' プロシージャ―内で生成されたインスタンスを参照している
    Console.WriteLine(p2.value.ToString())

    '結果
    '5
    '5

ByVal と ByRef の引数にクラスオブジェクトを与えています。Byref はプロシージャ内でインスタンスを生成したクラスオブジェクトを呼び出し元に返す場合に使用します。ByVal で定義されたパラメータに対して、プロシージャで生成したインスタンスを設定しても、呼び出し元では使用することはできません。C言語による、ポインタとダブルポインタの違いと感覚は同じでしょうか。

パラメータを省略可能にする ( Optional )

Optional キーワードを使用することで、パラメータを省略可能にすることができます。パラメータが省略された場合はあらかじめ定義しておいたデフォルト値が使用されることになり、パラメータが省略されずに与えられた場合はその値がプロシージャに渡されます。Sub と Function の違いはないのでここでは Sub プロシージャの例を掲載します。

    ' Optionalで省略可能なパラメータ p2 を定義する。
    ' 省略されて呼び出された場合は、0が格納される。
    Public Sub OptionalSub(ByVal p1 As Integer, Optional ByVal p2 As Integer = 0)
        Console.WriteLine("p1 = " + p1.ToString())
        Console.WriteLine("p2 = " + p2.ToString())
    End Sub

    ' ------------------------------------------------------------
    ' 呼び出し元のコード
    ' ------------------------------------------------------------
    Dim p1, p2 As Integer
    p1 = 0 : p2 = 1 ' パラメータの初期化(参考) ":" で区切ることで1行で記述できる

    OptionalSub(p1) ' p2 パラメータを省略
    OptionalSub(p1, p2) ' パラメータを省略しない  

名前付きパラメータ

プロシージャの呼び出し元は、プロシージャに定義された順番でパラメータを与える必要がありますが、名前付パラメータを使えば、呼び出し元でパラメータを任意の順で与えることができるようになります。以下に、Optional キーワードを同時に利用したサンプルを示します。

    '------------------------------------------------
    ' 呼び出し元
    '------------------------------------------------
    Named_Param(1, 2)                  ' Named_Param(1,2,0,0)
    Named_Param(p1:=1, p2:=2)          ' Named_Param(1,2,0,0)
    Named_Param(p2:=2, p1:=1)          ' Named_Param(1,2,0,0)
    Named_Param(p2:=2, p1:=1, p4:=4)   ' Named_Param(1,2,0,4)

    ' パラメーター省略可能プロシージャ―の定義
    Public Sub Named_Param(ByVal p1 As Integer, ByVal p2 As Integer, _
                           Optional ByVal p3 As Integer = 0, _
                           Optional ByVal p4 As Integer = 0)

        Console.WriteLine("p1 = " + p1.ToString())
        Console.WriteLine("p2 = " + p2.ToString())
        Console.WriteLine("p3 = " + p3.ToString())
        Console.WriteLine("p4 = " + p4.ToString())

    End Sub

このサンプルからわかるように、前方に定義されている Optional パラメータのみを省略したまま、後方に定義されている Optional パラメータを与えることができるようになります。

出来るということだけであり、お勧めはしません。。

スポンサーリンク


Pocket

Leave a Comment

Your email address will not be published. Required fields are marked *