넘어가는 것은 값의 사본이다
메서드를 부를 때 괄호에 값을 넣습니다. 그럼 그 값이 어떻게 넘어갈까요.
void AddTen(int n)
{
n = n + 10;
Console.WriteLine(n);
}
int score = 50;
AddTen(score);
Console.WriteLine(score);
AddTen 안에서는 60 이 나옵니다. 그럼 마지막 줄은 무엇이 나올까요.
50 입니다.
부르는 쪽 이름과 받는 쪽 이름은 남남이다
먼저 말을 정리하고 갑니다.
- 정의에 적는 것이 매개변수입니다. 위에서
int n입니다. - 호출할 때 실제로 넣는 것이 인수입니다. 위에서
score입니다.
이름이 달라도 됩니다. 같아도 됩니다. 서로 아무 상관이 없기 때문입니다. 매개변수 이름은 메서드 안에서만 통합니다. 밖에서는 무슨 이름이든 상관없습니다.
int score = 50;
int point = 30;
AddTen(score);
AddTen(point);
AddTen(80); // 이름 없는 값을 그대로 넣어도 됩니다
AddTen 은 받은 것이 score 인지 point 인지 80 인지 모릅니다.
값만 받습니다.
값이 복사되어 들어간다
앞에서 변수는 값을 담는 자리라고 했습니다. 메서드를 부를 때 일어나는 일은 그 값을 새 자리에 옮겨 적는 것입니다.
자리가 두 개입니다. 밖의 score 와 안의 n 은 다른 자리입니다.
n 을 고쳐도 score 는 모릅니다.
종이에 적은 숫자를 불러 주고 상대가 자기 종이에 받아 적은 것과 같습니다. 상대가 자기 종이의 숫자를 고쳐도 내 종이는 그대로입니다.
그래서 값을 바꾸려면 돌려받는다
밖의 값을 바꾸고 싶으면 돌려받아서 다시 담습니다.
int AddTen(int n)
{
return n + 10;
}
int score = 50;
score = AddTen(score); // 돌려받은 것을 다시 담습니다
Console.WriteLine(score); // 60
앞에서 문자열 메서드가 이랬습니다. s.ToUpper() 는 아무 일도 안 일어나고
s = s.ToUpper() 라야 바뀌었습니다.
이유가 이제 보입니다. 특별한 규칙이 아니라 메서드가 원래 그렇게 동작하기 때문입니다. 받은 것을 고쳐도 부른 쪽에는 안 보이니, 결과를 돌려주는 것 말고는 알릴 방법이 없습니다.
안에서 마음대로 써도 된다
사본이라는 성질에는 좋은 점도 있습니다. 매개변수를 안에서 자유롭게 고쳐 써도 밖에 영향이 없습니다.
int Countdown(int n)
{
int total = 0;
while (n > 0)
{
total += n;
n--; // 매개변수를 직접 줄여도 됩니다
}
return total;
}
n 을 반복문 변수처럼 써 버렸습니다. 그래도 부른 쪽 값은 멀쩡합니다.
따로 변수를 만들어 옮겨 담을 필요가 없습니다.
다만 읽기에는 헷갈릴 수 있습니다. 매개변수는 “받은 값” 이라는 뜻이 강해서, 중간에 다른 뜻으로 바뀌면 읽는 사람이 되짚어야 합니다. 길어지는 메서드에서는 새 변수를 만드는 편이 낫습니다.
목록을 넘기면 결과가 다르다
여기까지는 int 하나를 넘겼습니다. 그런데 List 나 배열을 넘기면 이야기가 달라집니다.
void AddItem(List<int> list)
{
list.Add(99);
}
List<int> nums = new List<int> { 1, 2 };
AddItem(nums);
Console.WriteLine(nums.Count); // 3
이번에는 밖이 바뀝니다. 앞에서 본 것과 반대입니다.
지금 단계에서는 그런 경우가 있다는 것만 알아 두면 됩니다.
이유를 제대로 말하려면 List 를 담은 변수 안에 실제로 무엇이 들어 있는지를 봐야 하는데,
그건 클래스와 객체를 다룰 때 정리합니다.
당장 기억할 것은 하나입니다.
숫자나 글자 하나를 넘겼다면 안에서 무엇을 하든 밖은 그대로입니다.
바뀌길 원하면 return 으로 돌려받습니다.
정리
- 정의에 적는 것이 매개변수, 호출할 때 넣는 것이 인수입니다.
- 매개변수 이름은 메서드 안에서만 통합니다. 밖의 변수 이름과 상관없습니다.
- 넘어가는 것은 값의 사본입니다. 안과 밖은 다른 자리입니다.
- 그래서 안에서 매개변수를 고쳐도 밖은 그대로입니다.
- 밖의 값을 바꾸려면
return으로 돌려주고 다시 담습니다. - 매개변수를 안에서 마음대로 써도 안전합니다. 다만 읽기에 헷갈릴 수 있습니다.
List나 배열처럼 여러 개를 담는 것을 넘기면 결과가 다릅니다.