前回は、配列をやりました。

今回は、関数(メソッド)です。プログラミングの関数は、主のプログラム部分とは別の場所に決まった処理を定義しておき、いつでも利用できるようにしておくものです。算数のように変数に値を渡して、方程式のように使用することもできます。記事の随所にも出てきた数値を文字列にするToString()も関数です(クラスに属する関数)。

構文は以下のようになります。

関数(メソッド)の書き方

戻り値の型 関数名(引数部){
 関数内の処理;
 return 戻り値;
}

早速、関数を使ったサンプルソースです。

C#

public class kansu{
    // 決まった文字列を出力するメソッド
    public static void outputLine(){
        System.Console.WriteLine("=-=-=-=-=");
    }
    // 三角形の面積を計算するメソッド
    public static double calc_menseki_sankaku(int teihen, int takasa){
        double ret = (teihen*takasa)/2 ;
        return ret;
    }
    public static void Main(){
        // 文字列を出力するメソッドの呼び出し
        outputLine();
        // calc_menseki_sankakuを呼び出している
        double kekka = calc_menseki_sankaku(5,10);
        System.Console.WriteLine(kekka.ToString());
        // もう一度 文字列を出力するメソッドの呼び出し
        outputLine();
    }
}

結果

=-=-=-=-=
25
=-=-=-=-=
1つ目のoutputLine()関数は、値を戻さない関数です。main関数と同じく値を戻さない処理だけの関数は頭にvoidを記述します。(publicstaticは、"クラス"の記事などで説明したいと思います)

関数名は、英数字とアンダーバーが使用できます。値を引き渡す(引数部)は、省略したり複数引き渡すことができます。outputLineの処理内容は、単純ですが出力結果に文字列を出力するというものです。main側から呼び出したい時は、outputLine();と記述することで、関数へプログラム処理をジャンプさせることができます。関数呼び出しは、引数がなくても括弧”( )”を忘れずにつけましょう。関数側のプログラム処理が終われば、mainへと戻ってきます。

続いて2つ目のcalc_menseki_sankaku(int ,int)関数は、三角形の面積を計算し、doubleを戻り値としています。第一引数にteihenと第二引数にtakasaの値を引数に渡して、関数内で計算しています。関数の最後で、returnを記述し、関数の戻り値型と同じ型を返しています。


複雑なプログラムをmain関数にずらずらと書いていくと、ソースコードがとても長くなり、重複する処理が多くなります。関数を用いることにより、簡素化やメンテナンス性をよくしていきます。

引数の値渡し、参照渡し

引数の型の前にrefをつけることにより参照渡しになります。先ほどの例であったような引数に何も記述していないものは値渡しとなります。

これも挫折しやすいポイントですが、C言語のポインタより理解しやすいと思います。違いを説明しますと、「値を渡していいる」のが値渡し、「変数のアドレスを渡している」のが参照渡しになります。アドレスとは、コンピュータメモリの番地のようなものです。

171105_sansyo_watashi


参照渡しでは、呼び出し元の変数の値を関数内で変更することができます。サンプルソースで確認してみましょう。

C#

public class kansu2{
    // 値渡し
    public static void kasan1(int kazu){
        kazu++;
    }
    // 参照渡し
    public static void kasan2(ref int kazu){
        kazu++;
    }
    public static void Main(){
        int a = 1;
        int b = 1;
        kasan1(a);
        kasan2(ref b);
        System.Console.WriteLine("a=" + a.ToString());
        System.Console.WriteLine("b=" + b.ToString());
    }
}

結果

a=1
b=2
kasan1とkasan2という内部処理は全く同じ関数です。kasan2の第一引数にrefをつけています。mainの呼び出し元ではa変数をkasan1にb変数をref付きでkasan2に引き渡してます。結果のa変数は、値が変わっていないのに対して、b変数は値が変わっています。a変数の値"1"が渡されコピーされた値が使われ、b変数は変数自身が引き渡されて書き換えられています。

参照渡しの中でも呼び出し元で変数を初期化するrefとは違い、関数内で変数を初期化するoutというものもあります。戻り値でも結果を受け取れますが、outをつければ複数結果を受け取ることができます。(outは結果受け取り専用のようなもの)

参照型の値渡し

参照型と参照渡しで名前が似ていますが、意味が違います。

値型と参照型を簡単に説明すると、intやdoble型は、初期化時に変数に直接値を確保しますが、配列やクラスは、変数にメモリアドレスがセットされ、間接的に値を操作します。値型はスタックメモリに、参照型はピープメモリにと、メモリの場所も異なります。今は、2種類の型があるんだぁ程度で考え、後々深く理解すればよいと思います。

C#

public class kansu3{
    // 参照型を値渡し
    public static void conv_hairetu(int[] arr){
        for(int i=0;arr.Length>i;i++){
            arr[i]+=1;
        }
    }
    public static void Main(){
        int[] a = new int[]{1,2,3};
        conv_hairetu(a);
        foreach(int c in a){
            System.Console.WriteLine(c.ToString());    
        }
    }
}

結果

2
3
4
と、refをつけていないのに、結果のように加算されました。このように、参照型を引き渡すと実態の変数も変わるので要注意です!参照渡し同様に内部ではメモリアドレスが引き渡されている。

※ 因みに、string型は特殊で値型っぽいですが参照型です!文字を表すchar型は値型です。文字が配列のようなものになったのがstring型(クラス)です。ですが、stringは値型のように内部で処理されるので、そのようにプログラムを組んでいきます。

次回は、変数のスコープに進みたいと思います。