1. 메서드 기본
메서드는 함수와 비슷한 개념으로 특정 목적을 위해 작성된 코드를 묶어 놓은 것을 말합니다. 보통 클래스에 소속된 함수를 메서드라고 부르며 일반적인 함수와는 구분되는 개념입니다.
using System;
using static System.Console;
namespace Test
{
class MyTestApp
{
static void Main(string[] args)
{
Plus(10, 20);
}
static void Plus(int i, int j)
{
WriteLine(i + j);
}
}
}
예제에서는 Plus()메서드를 만들고 이를 Main() 메서드에서 호출하여 두 숫자의 합을 확인하고 있습니다. 필요에 따라 특정 메서드에서 자기 자신을 스스로 호출하는 경우도 있는데 이를 '재귀 호출'이라고 합니다.
C#은 객체지향 프로그래밍 언어인데 객체지향에서 메서드는 반드시 클래스안에 속해있어야 합니다. 이 때문에 예제는 Main() 메서드나 Plus() 메서드 모두 MyTestApp이라는 클래스 안에서 정의되고 있습니다.
함수는 어떤 처리를 진행한뒤 그대로 종료할 수 있지만 다음과 같이 특정 값을 반환하는 형태를 가질 수도 있습니다.
using System;
using static System.Console;
namespace Test
{
class MyTestApp
{
static void Main(string[] args)
{
int r = Plus(10, 20);
WriteLine(r);
}
static int Plus(int i, int j)
{
return i + j;
}
}
}
Plus() 메서드는 2개의 매개변수에서 값을 받아 이를 더한 결과를 return문으로 반환하고 있습니다. static옆에 int는 Plus() 메서드가 int형의 데이터를 반환할 것임을 알려주고 있고 이 때문에 Main() 메서드에서는 함수의 실행결과를 int변수 r로 받아오고 있습니다.
참고로 Main()메서드 처럼 반환 형식에 void 키워드가 사용된 경우는 해당 함수는 아무런 값도 반환하지 않음을 의미하며 static은 클래스의 한정자로서 해당 메서드가 클래스에서 바로 호출될 수 있도록 하겠다는 것을 의미합니다. 자세한 사항은 나중에 다루겠지만 보통 클래스는 클래스의 객체를 생성하고 그 객체를 통해 메서드가 호출되는데 static은 객체를 생성하지 않고도 곧장 클래스에서 메서드를 호출할 수 있도록 합니다.
2. Ref 매개변수
매개변수란 메서드에서 값을 전달받을 때 사용하는 변수를 말합니다. 아래 예제에서 Plus에 사용된 i와 j변수가 매개변수에 해당합니다. 일반적인 경우 메서드를 호출할 때 매개변수에 호출자(Main() 메서드)의 변숫값을 그대로 전달하면 변수간 값의 복사가 이루어집니다.
class MyTestApp
{
static void Main(string[] args)
{
int i = 10;
int j = 20;
int r = Plus(i, j);
WriteLine(r);
}
static int Plus(int i, int j)
{
return i + j;
}
}
따라서 Main()메서드의 i, j값과 Plus() 메서드의 i, j값은 각각의 메서드에서 독립적으로 동작하게 됩니다. 즉, Main() 메서드에서 변수의 값을 아무리 바꿔도 Plus() 메서드에서 고의적으로 자신의 i, j매개변수 값을 바꾸지 않는 한 해당 매개 변숫값에는 영향을 끼치지 않는다는 것을 의미합니다.
하지만 매개변수를 ref로 정의하는 경우에는 메서드를 직접 호출하는 호출자의 인수값을 참조하는 형태로 값을 전달합니다.
class MyTestApp
{
static void Main(string[] args)
{
int i = 10;
int j = 20;
RefMethod(ref i, ref j);
WriteLine(i + j); //RefMethod()함수에서 매개변수의 값을 바꾸면 이를 호출하는 Main()함수의 변수값도 바뀌게 되므로 결과는 50.
}
static void RefMethod(ref int i, ref int j)
{
i = 20;
j = 30;
}
}
RefMethod()에서는 두개의 매개변수를 정의할 때 ref키워드를 통해 참조 형식으로 매개변수를 정의하였으며 Main() 메서드에서도 RefMethod() 메서드를 호출할 때 ref키워드로 매개 변숫값을 전달하고 있습니다.
이와 같은 상태가 되면 각 메서드에서 값을 바꿀때 마다 해당 변수를 사용하는 다른 메서드에도 변숫값의 영향을 받게 됩니다.
3. ref 반환
메서드를 호출할때 ref키워드를 사용해 값을 참조 형식으로 전달했는데 메서드에서 값을 반환할 때도 ref 키워드로 참조 형식의 값을 반환할 수 있습니다.
using System;
using static System.Console;
namespace Test
{
class MyTestApp
{
static void Main(string[] args)
{
RefValue rv = new RefValue();
ref int result = ref rv.GetResult();
rv.ReadResult(); //원래값 100
result = 200;
rv.ReadResult(); //값 변경 이후 200
}
}
class RefValue
{
private int result = 100;
public ref int GetResult()
{
return ref result;
}
public void ReadResult()
{
WriteLine(result);
}
}
}
RefValue클래스의 GetResult()메서드에서는 ref int로 참조 형식의 int형 값을 반환하는 메서드임을 알려주고 있고, 실제 return에서도 ref키워드를 사용해 result변숫값을 반환하고 있습니다. 참고로 지역변수에는 참조 반환을 설정할 수 없습니다.
Main() 메서드에서는 RefValue클래스의 GetResult() 메서드를 호출하고 있는데 참조 형식으로 값을 반환하는 메서드라 할지라도 값을 받을 때, 그리고 값을 받는 변수 모두 ref키워드를 사용해야 참조 형식의 데이터를 받아올 수 있습니다.
예제에서는 값을 받아오고 난 후 Main()메서드 안에서 지역변수인 result값을 변경하고 있는데 현재 Main() 메서드의 result지역변수는 참조형 변수이므로 RefValue클래스의 멤버 변수인 result변숫값도 같이 바뀌는 것을 알 수 있습니다.
4. out 매개변수
ref와 같이 참조형식이지만 해당 매개변수에는 값을 지정할 수 없고 오로지 값을 가져오는 용도로만 사용할 수 있다는 차이가 있습니다.
static void Main(string[] args)
{
int result_plus = 0;
int result_minus = 0;
Calc(100, 200, out result_plus, out result_minus);
WriteLine(result_plus); //300
WriteLine(result_minus); //-100
}
static void Calc(int i, int j, out int plus, out int minus)
{
plus = i + j;
minus = i - j;
}
Calc() 메서드는 2개의 out매개변수를 사용하고 있는데 Main() 메서드에서 Calc() 메서드를 호출할 때 out키워드를 사용해 값을 확인할 변수를 지정해 주고 있습니다.
out은 출력전용이기에 사실상 result_plus와 result_minus변수의 값은 무의미하며 아예 값을 지정하지 않은 변수를 넘겨주거나 변수의 선언 자체를 무시하는 것도 가능합니다.
static void Main(string[] args)
{
//int result_plus = 0;
//int result_minus = 0;
Calc(100, 200, out int result_plus, out int result_minus);
WriteLine(result_plus); //300
WriteLine(result_minus); //-100
}
다만 위와 같이 구현하는 경우 out매개변수에 반드시 값의 데이터형식을 지정해 줘야 합니다.
Calc() 메서드에서는 out매개변수로 전달된 변수에 계산 값을 저장하고 이를 호출한 Main() 메서드 안에서 해당 값을 확인하고 있습니다. ref키워드를 사용해도 동일한 기능을 구현할 수 있지만 out키워드를 사용하게 되면 이를 사용하는 메서드에서는 반드시 해당 변수에 값을 저장해야 하는 제한이 생기기 때문에 좀 더 안정적으로 메서드를 구현할 수 있습니다.
5. 메서드 오버로딩(Overloading)
오버 로딩은 동일한 메서드 이름으로 여러 형식의 매개변수가 지정되는 경우를 말합니다.
static void Main(string[] args)
{
int result = Calc(10, 20, 30);
WriteLine(result); //60
}
static int Calc(int i, int j)
{
return i + j;
}
static int Calc(int i, int j, int x)
{
return i + j + x;
}
예제에서 Calc() 메서드는 2가지 버전이 존재하는데 첫 번째는 매개변수가 2개인 버전과 두 번째 매개변수가 3개인 버전입니다. 메서드를 호출하는 입장에서는 매개변수의 개수에 따라 호출하는 메서드가 달라질 것이므로 동일한 메서드 이름을 사용한다고 하더라도 문제 될 것이 없습니다. 굳이 매개변수의 개수를 달리하는 경우가 아니라도 매개변수의 데이터형을 통해서 각각의 메서드를 구분할 수도 있습니다.
static void Main(string[] args)
{
float result = Calc(10.12f, 20.24f);
WriteLine(result); //30.36
}
static int Calc(int i, int j)
{
return i + j;
}
static float Calc(float i, float j)
{
return i + j;
}
6. params 매개변수
매개변수를 배열로 선언한 형태로서 하나의 데이터 형식으로 몇 개 정도의 인수가 전달될지 알 수 없는 경우에 사용됩니다.
static void Main(string[] args)
{
Plus(1, 2, 3, 4, 5, 6, 7);
}
static void Plus(params int[] args)
{
foreach(int i in args)
{
WriteLine(i);
}
}
params키워드를 사용해 배열 변수를 선언하는 것과 동일한 방법으로 매개변수를 배열로 선언하며 단독적으로만 사용할 수 있고, 다른 매개변수와는 혼용할 수 없습니다.
static void Plus(params int[] args, int i) //불가능
{
foreach(int i in args)
{
WriteLine(i);
}
}
7. 명명된 인수
메서드를 호출할 때 어느 매개변수에 어떤값을 줄지 지정하는 것을 말합니다. 일반적인 경우는 매개변수가 지정되는 순서에 따라 값이 할당되지만
class MyTestApp
{
static void Main(string[] args)
{
int result = Plus(10, 20);
WriteLine(result);
}
static int Plus(int first, int second)
{
return first + second;
}
}
명명된 인수를 사용하면 순서와는 상관없이 임의의 매개변수를 지정해 호출할 수 있습니다.
8. 선택적 인수
선택적 인수는 미리 매개변수에 기본값을 설정한 것으로 메서드를 호출할때 기본값 외에 다른 값이 필요하지 않다면 생략하여 메서드를 호출할 수 있습니다.
class MyTestApp
{
static void Main(string[] args)
{
int result = Plus(10);
WriteLine(result);
}
static int Plus(int first, int second = 20)
{
return first + second;
}
}
Plus() 메서드에서 second매개변수의 기본값을 20으로 지정하였습니다. 따라서 Plus() 메서드를 호출할 때 second매개변수의 값이 지정된 기본값으로 사용되는 경우라면 first매개 변숫값만을 전달하여 메서드를 호출하면 됩니다.
기본값이 지정된 매개변수는 하나 이상 지정하는 것이 가능하지만 기본값이 없는 매개변수 뒤에만 올 수 있습니다.
9. 로컬 함수
메서드 안에서 별도로 선언되고 사용되는 함수입니다. 클래스의 멤버가 아니므로 메서드가 아닌 '함수'로 명명되며 메서드처럼 클래스 외부에서 호출될 수 없습니다.
class MyTestApp
{
static void Main(string[] args)
{
int second = 20;
int result = Plus(10);
int Plus(int first)
{
return first + second;
}
WriteLine(result);
}
}
로컬 함수는 메서드 안에서만 사용되므로 public이나 private처럼 한정자를 붙일 수 없습니다. 하지만 메서드안에서 사용되는 지역변수를 공유할 수 있다는 특징이 있는데 예제에서는 second라는 지역변수를 Plus() 함수에서 사용하여 결괏값을 되돌려 주고 있습니다.
'.NET > C#' 카테고리의 다른 글
[C#] 인터페이스와 추상클래스 (2) | 2021.10.07 |
---|---|
[C#] 클래스(Class) (0) | 2021.10.06 |
[C#] 제어문 (0) | 2021.09.24 |
[C#] 연산자 (0) | 2021.09.23 |
[C#] 데이터 (2) | 2021.09.23 |