C# - 引数 - 値渡しと参照渡し
メソッドの引数を参照渡しで行う場合は、仮引数だけでなく、実引数側にも ref をつける。これはメソッドの引数にしたことで、メソッド側から書き換えが発生する可能性のあることを明示する為である。
メソッドの結果を引数経由で呼び出し側に渡す用途の場合は、ref の代わりに out を使用する。このため呼び出し側で out を付けて渡す実引数は必ず変数でなければならない。またメソッド側から代入が行われるので値が未定の(代入していない)変数も使用できる。代わりにメソッド内では、outを付けた仮引数を読み出すことはできない。
参照型変数を参照渡しでメソッドに渡して、メソッド内において新規オブジェクトを代入(参照)した場合、呼び出し側の変数においても新規オブジェクトが参照され、元々参照していたオブジェクトを参照しなくなるので注意。
using System; //メソッドの引数 // 値渡しと参照渡し class MyMain { public static void Main(string[] args) { int a = 1; int b = 2; int c; int[] aa = new int[]{1,2,3}; int[] bb = new int[]{4,5,6}; Console.WriteLine("値型変数 値渡し"); Console.WriteLine("Var is {0}", a); ByVal(a); Console.WriteLine("Var is {0}", a); Console.WriteLine("-----"); Console.WriteLine("値型変数 参照渡し(ref)"); Console.WriteLine("Var is {0}", b); ByRef(ref b); Console.WriteLine("Var is {0}", b); Console.WriteLine("-----"); Console.WriteLine("値型変数 参照渡し(out)"); //Console.WriteLine("Var a is {0}", c); //エラー ByOut(out c); Console.WriteLine("Var is {0}", c); Console.WriteLine("-----"); Console.WriteLine("参照型変数 値渡し"); Console.Write("Var is "); PrintArray( aa ); ByVal2( aa ); Console.Write("Var is "); PrintArray( aa ); Console.WriteLine("-----"); Console.WriteLine("参照型変数 参照渡し"); Console.Write("Var is "); PrintArray( bb ); ByRef2( ref bb ); Console.Write("Var is "); PrintArray( bb ); } //値型変数 値渡し private static void ByVal(int arg) { Console.WriteLine("ByVal Proc : arg is {0}", arg); Console.WriteLine("ByVal Proc : assign 100 to arg"); arg = 100; Console.WriteLine("ByVal Proc : arg is {0}", arg); } //値型変数 参照渡し(ref) private static void ByRef(ref int arg) { Console.WriteLine("ByRef Proc : arg is {0}", arg); Console.WriteLine("ByRef Proc : assign 100 to arg"); arg = 100; Console.WriteLine("ByRef Proc : arg is {0}", arg); } //値型変数 参照渡し(out) private static void ByOut(out int arg) { //Console.WriteLine("ByVal Proc : arg is {0}", arg); //エラー Console.WriteLine("ByOut Proc : assign 100 to arg"); arg = 100; Console.WriteLine("ByOut Proc : arg is {0}", arg); } //参照型変数 値渡し private static void ByVal2(int[] arg) { Console.Write("ByVal Proc : arg is "); PrintArray( arg ); Console.WriteLine("ByVal Proc : assign NewArray(100,200,300)) to arg"); arg = new[]{100, 200, 300}; Console.Write("ByVal Proc : arg is "); PrintArray( arg ); Console.WriteLine("ByVal Proc : assign 999 to arg[0]"); arg[0] = 999; Console.Write("ByVal Proc : arg is "); PrintArray( arg ); } //参照型変数 参照渡し(ref) private static void ByRef2(ref int[] arg) { Console.Write("ByRef Proc : arg is "); PrintArray( arg ); Console.WriteLine("ByRef Proc : assign NewArray(100,200,300)) to arg"); arg = new[]{100, 200, 300}; Console.Write("ByRef Proc : arg is "); PrintArray( arg ); Console.WriteLine("ByRef Proc : assign 999 to arg[0]"); arg[0] = 999; Console.Write("ByRef Proc : arg is "); PrintArray( arg ); } private static void PrintArray(int [] arg) { Console.Write("[ "); foreach(var e in arg) { Console.Write("{0} ", e); } Console.WriteLine("]"); } }
実行結果
値型変数 値渡し Var is 1 ByVal Proc : arg is 1 ByVal Proc : assign 100 to arg ByVal Proc : arg is 100 Var is 1 ----- 値型変数 参照渡し(ref) Var is 2 ByRef Proc : arg is 2 ByRef Proc : assign 100 to arg ByRef Proc : arg is 100 Var is 100 ----- 値型変数 参照渡し(out) ByOut Proc : assign 100 to arg ByOut Proc : arg is 100 Var is 100 ----- 参照型変数 値渡し Var is [ 1 2 3 ] ByVal Proc : arg is [ 1 2 3 ] ByVal Proc : assign NewArray(100,200,300)) to arg ByVal Proc : arg is [ 100 200 300 ] ByVal Proc : assign 999 to arg[0] ByVal Proc : arg is [ 999 200 300 ] Var is [ 1 2 3 ] ----- 参照型変数 参照渡し Var is [ 4 5 6 ] ByRef Proc : arg is [ 4 5 6 ] ByRef Proc : assign NewArray(100,200,300)) to arg ByRef Proc : arg is [ 100 200 300 ] ByRef Proc : assign 999 to arg[0] ByRef Proc : arg is [ 999 200 300 ] Var is [ 999 200 300 ]