レガシーコードからの脱却

レガシーな職場でも独学でどうにか頑張っていくブログです。

【お勉強記録】C#文法学び直し。ref

参照渡し

メソッドに引数を渡すときに値ではなく引数の参照を渡すことができます。 メソッドと呼び出し側双方ともに「ref」をつけることで参照渡しであると明示します。 呼び出し側でrefと書くのは知らないうちに参照渡しになっていて、値が書き換えられているといったようなことを防ぐためのようです。

using System;

namespace test
{
    class Program
    {
        delegate void Greet();

        static void Main(string[] args)
        {
            int a = 100;
            Console.WriteLine(a.ToString());
            Program.Test(ref a);
            Console.WriteLine(a.ToString());

            Console.ReadLine();
        }   

        static void Test(ref int reference)
        {
            reference= 10;
        }

    }
    
}

実装結果をみると直接aが書き換えられているのがわかります。

100
10

refを使うことで、複数の戻り値をもつメソッドを実現できます。

using System;

namespace test
{
    class Program
    {
        delegate void Greet();

        static void Main(string[] args)
        {
            //参照渡しのため値初期化必要
            int kotae = 0;
            int amari = 0;
            Program.Dev(3, 2, ref kotae, ref amari);
            Console.WriteLine("答え・・・" + kotae.ToString() + " あまり・・・" + amari.ToString());

            Console.ReadLine();
        }

        static void Dev(int left, int right, ref int kotae, ref int amari)
        {
            kotae = left / right;
            amari = left % right;
        }

    }

}

実行結果

答え・・・1 あまり・・・1

refを使うことで複数の戻り値を持つメソッドを実現できました。 ただし、C#では返すだけの目的で引数を使用する場合のために「out」が用意されています。

先ほどのサンプルをoutで書き換えた結果は以下のようになります。

using System;

namespace test
{
    class Program
    {
        delegate void Greet();

        static void Main(string[] args)
        {
            //初期化の必要なし
            int kotae;
            int amari;
            Program.Dev(3, 2, out kotae, out amari);
            Console.WriteLine("答え・・・" + kotae.ToString() + " あまり・・・" + amari.ToString());

            Console.ReadLine();
        }

        static void Dev(int left, int right, out int kotae, out int amari)
        {
            kotae = left / right;
            amari = left % right;
        }

    }

}

kotae、amariともに値を返すためのものなので、「out」を使ってます。 先ほどは呼び出し型で設定する引数の初期化が必要でしたが、今回は値を設定しないでもコンパイル可能です。 (refだとコンパイルエラー)

うーん…使い分けとしては、メソッド内でも引数の値を使いたい場合はref戻したいだけの時はoutでいいのでしょうか?