値渡し、参照渡し
■値渡し
実際は参照型の値渡しをしている。
※@lensoukoさんのコメントを参考に修正。
//値渡し(参照型の値渡し)
public static void main(String[] args) {
int[] array = {1,2};
Console.WriteLine(array[1]);//2
call(array);
Console.WriteLine(array[1]);//100
}
private static void call(int[] array) {
array[1] = 100;
Console.WriteLine(array[1]);//100
int[] array2 = {1,200};
array = array2;
Console.WriteLine(array[1]);//200
}
■参照渡し
ref修飾子またはout修飾子を使う。
二つの違いは以下。
・メソッド呼び出し元の変数の初期化
out修飾子 → 不要
ref修飾子 → 必須
・メソッド呼び出し先での変数の初期化(変数への値の割り当て)
out修飾子 →必須(必ず割り当てする必要あり)
ref修飾子 → 任意(どちらでもよい)
//参照渡し(ref修飾子)
public static void main(String[] args) {
int[] array = {1,2};
Console.WriteLine(array[1]);//2
call(ref array);
Console.WriteLine(array[1]);//200
}
private static void call(ref int[] array) {
array[1] = 100;
Console.WriteLine(array[1]);//100
int[] array2 = {1,200};
array = array2;
Console.WriteLine(array[1]);//200
}
//参照渡し(out修飾子)
public static void main(String[] args) {
int[] array = {1,2};
Console.WriteLine(array[1]);//2
call(out array);
Console.WriteLine(array[1]);//200
}
private static void call(out int[] array) {
//array[1] = 100;
//Console.WriteLine(array[1]);//100
int[] array2 = {1,200};
array = array2;
Console.WriteLine(array[1]);//200
}
■余談
Javaだとrefとかoutとかはなくて、
値渡し(参照型の値渡し)しかない。
クロージャ
■説明
ローカル変数を捕獲(キャプチャ)しているローカル関数や匿名関数をクロージャという。
static void Main()
{
var x = 1;
// ローカル関数内でローカル変数xをキャプチャ
void f(int n) => x = n;
Console.WriteLine(x); // 1
f(2);
Console.WriteLine(x); // 2
}
■余談
Javaだとこれはできない。(クロージャは存在しない)
ローカル関数を定義してるところで怒られる。
(Javaだとxは暗黙的にfinalが付く)
public static void main(String[] args)
{
var x = 1;
// コンパイルエラー
// local variables referenced from a lambda expression must be final or effectively final
// IntUnaryOperator op = n -> x = n;
// ^
IntUnaryOperator op = n -> x = n;
System.out.println(x);
op.applyAsInt(2);
System.out.println(x);
}
クロージャぽいことはできる。(オブジェクトを渡せばいい)
public static void main(String[] args)
{
int[] array = {1,2};
IntUnaryOperator op = n -> array[0]=n;
System.out.println(array[0]);//1
op.applyAsInt(2);
System.out.println(array[0]);//2
}