[C# Basic] 메소드 사용법
업데이트:
C#의 기초부터 차근차근 다시 한 번 짚어보자.
이번에는 메소드를 작성하고 활용하는 방법에 대해 알아보자
* 메소드란
class 클래스이름{
한정자 반환형식 메소드이름(매개변수목록){
//실행하고자하는 코드
return 메소드결과; // 메소드의 반환형식과 형이 맞아야 함
}
}
- 객체지향 프로그래밍 언어에서 사용하는 용어로 일련의 코드를 하나의 이름 아래 묶은 것
- 동일한 기능을 여러번 기술할 필요 없이 하나의 메소드로 만들어두면 호출하는것만으로 해당 기능을 반복해서 사용할 수 있다
- 반환형식이 없는 경우도 있다. 이 경우 메소드의 반환형식에 void를 사용하면 된다
* static 한정자
- static은 메소드나 필드가 클래스의 인스턴스가 아닌 클래스 자체에 소속되도록 하는 한정자
- 해당 클래스의 인스턴스를 만들지 않고 바로 해당 메소드를 호출할 수 있게 해준다.
* 메소드의 return
private void Test(){
int a = 1;
if(a == 1){
Console.WriteLine("a는 1");
return;
}
else{
Console.WriteLine("a는 1이 아님");
return;
}
}
- return을 만나면 해당 메소드는 실행을 멈추고 값을 반환하면서 종료된다
- 반환형식이 없는 경우에도 return; 만 기재하여 흐름을 멈추는 것이 가능하다
* 메소드의 매개변수
- 메소드에 매개변수를 전달하는 경우 변수 자체가 메소드 안으로 전달되는 것이 아니라, 변수가 가지고 있는 데이터만 복사되어 전달된다. 즉 원본 변수와 별개의 메모리 공간을 사용하게 된다. 값형식이든 참조형식이든 동일하다.
private void Swap(int a, int b){
int temp = b;
b = a;
a = temp;
}
- 위 메소드가 호출되면 호출이 끝난 뒤 원본 변수 a와 b의 값은 그대로이다. 메소드가 매개변수를 그대로 사용하지 않고 복사해서 사용하기 때문이다.
- 위와 같이 메소드를 호출할 때 데이터를 복사해서 매개변수에 넘기는 것을 ‘값에 의한 전달’이라 한다
private void Swap(ref int a, ref int b){
int temp = b;
b = a;
a = temp;
}
int a = 1;
int b = 2;
Swap(ref a, ref b); // 메소드 호출시에도 ref 키워드를 붙여주어야 함
- 위 메소드의 매개변수는 ref 키워드를 사용하였다. 위와 같이 메소드가 만들어지면 해당 메소드에 매개변수를 전달할 때 원본 변수를 직접 참조하도록 전달한다. 즉 메소드 내에서 변수의 값이 변경되면 원본 변수도 동일하게 변경된다.
- ref 키워드를 사용해 변수를 넘기는 경우 이를 ‘참조에 의한 전달’이라 한다.
* 메소드의 결과를 참조로 반환
class Product{
private int price = 100;
public ref int GetPrice(){
return ref price;
}
public void PrintPrice(){
Console.WriteLine(price);
}
}
class MainApp{
static void Main(string[] args){
Product temp = new Product();
ref int refPrice = ref temp.GetPrice(); // refPrice를 변경하면 temp.price도 변경된다
temp.PrintPrice(); // 100 출력
Console.WriteLine(refPrice); // 100 출력
refPrice = 200;
temp.PrintPrice(); // 200 출력
Console.WriteLine(refPrice); // 200 출력
}
}
- 매개변수 전달시 참조에 의한 전달로 전달했던 원본 변수에 변경사항을 바로 적용할 수도 있고, 위 예제와 같이 참조로 값을 반환하여 해당 결과를 계속해서 다룰 수 있게 해주는 참조 반환값도 있다.
- ref 한정자를 이용해 메소드를 선언하고 return문에도 ref 키워드를 사용하여야 한다
- 반환받은 변수가 변경되면 참조하고있던 메소드 내의 참조값도 같이 변경되게 된다
* 출력 전용 매개변수
void Calc(int a, int b, ref int c, ref int d){
c = a + b;
d = a - b;
}
- ref 키워드를 이용해 하나 이상의 결과값을 반환하는 것이 가능하다.
void Calc(int a, int b, out int c, out int d){
c = a + b;
d = a - b;
}
- C#에서는 조금 더 안전한 방법으로 out 키워드를 이용한 출력 전용 매개변수 기능을 제공한다.
- ref 키워드는 매개변수를 넘기는 경우 해당 매개변수에 결과를 저장하지 않아도 컴파일러 오류 발생하지 않음
- out 키워드는 해당 매개변수에 결과를 저장하지 않으면 컴파일러가 에러메시지 출력
* 메소드 오버로딩
int Plus(int a, int b){
return a + b;
}
double Plus(double a, double b){
return a + b;
}
- 하나의 메소드 이름에 여러 개의 구현을 하는 것을 의미
- 매개변수의 개수와 형식을 가지고 메소드 호출시 어떤 버전을 호출할지 컴파일러가 결정
- 실행할 메소드를 찾는 과정은 컴파일 시점에 이뤄지므로 성능에는 이상이 없음
- 프로그래머의 이름에 대한 고민을 줄여주는 동시에 코드를 일관성있게 유지해주는 장점이 있음
* 가변길이 매개변수
int Sum(params int[] args){
int sum = 0;
foreach(int arg in args){
sum += arg;
}
return sum;
}
- 메소드를 매개변수의 수만 다르게하여 여러 버전으로 오버로딩 하고싶은 경우 가변길이 매개변수를 활용할 수 있음
- 동일한 데이터타입의 변수를 여러개 받는 경우 사용 가능. (변수의 개수만 다른 경우)
- 데이터타입이 다른 버전이 필요한 경우에는 오버로딩을 해서 활용해야 함
* 명명된 매개변수
void Print(string firstName, string LastName){
Console.WriteLine(firstName + Lastname);
}
Print(firstName:"보", Lastname:"노보노");
- 메소드 호출시 어떤 매개변수에 값을 할당할것인지 직접 지정 가능. (미지정시 순서대로 지정됨)
- 매개변수가 많아 눈으로 분간이 어려운 경우 명명된 매개변수가 코드분석에 도움을 줄 수 있음
* 선택적 매개변수
int Plus(int a, int b = 2){
return a + b;
}
Plus(1); // 3 반환
Plus(5, 4); // 9 반환
- 메소드의 매개변수는 기본값을 가질 수 있음. 메소드의 매개변수 작성시 초기화하듯 작성하면 됨
- 기본값을 가지는 매개변수는 메소드 호출시 데이터 할당을 생략할 수 있음
- 필요한 경우 데이터를 할당할수도 있음. 데이터를 할당하면 해당 데이터가 사용되고, 데이터를 할당하지 않으면 기본값이 사용됨
- 선택적 매개변수는 항상 필수 매개변수 뒤에 와야 함
- 메소드의 모호함이라는 단점이 있으니 이런 경우 명명된 매개변수를 통해 메소드를 호출하면 좀 더 보기 좋게 사용할 수 있음
* 오버로딩과 선택적매개변수
int Plus(int a, int b = 0){
return a + b;
}
int Plus(int a){
return a + 0;
}
Plus(1); // 이 경우 2번째 메소드가 호출됨
- 위 예제를 보면 메소드 호출시 매개변수를 1개만 넘겼다. 이 경우 선택적 매개변수와 오버로딩을 함께 사용한 코드로 인해 어떤 메소드가 호출될지 헷갈리는 문제가 발생한다.
- 위와 같은 문제가 없도록 선택적매개변수와 메소드오버로딩 둘 중 하나만 선택해서 사용하는 것이 좋다.
* 로컬 함수
- 로컬 함수는 메소드 안에서 선언된 함수이다. (메소드 안의 메소드라 생각하면 된다)
- 클래스의 멤버가 아니기 때문에 메소드가 아니라 함수라 표현한다
- 메소드와 다르지 않지만 자신이 존재하는 지역에 선언된 변수를 사용할 수 있다
- 메소드 밖에서 다시 쓸 일 없는 반복작업을 하나의 이름으로 묶어놓는데 적합하다