안녕하세요. 명월입니다.
이 글은 C#의 함수(Method)와 오버로딩과 재귀 호출에 대한 글입니다.
프로그램을 작성해서 실행하면 Main함수에서 위에서 아래로 순차적으로 실행됩니다. 이런 순차적 방식과 제어문을 통한 분기와 반복만으로도 프로그램을 작성할 수 있습니다.
그러나 점점 프로그램이 복잡해지고 비슷한 구문이 많아진다면 이런 방식만으로는 한계가 있습니다.
그래서 프로그램에서는 이것을 극복하기 위한 함수가 있습니다. 함수는 수학에서의 함수와 같은 의미로 임의의 원소(파라미터)를 대입하므로 결과가 나오는 이항관계식을 뜻합니다.
[접근제한자] [반환 타입] 함수 이름 (파라미터)
{
........
return 반환 타입;
}
정확하게 함수에 파라미터를 넣으면 함수 안의 연산을 타고 반환 타입의 형식으로 값이 반환하게 됩니다.
using System;
namespace Example
{
class Program
{
// ExecuteMethod1 함수
private static int ExecuteMethod1(int a)
{
// 파라미터에서 a의 값을 받으면 10을 곱해서 반환한다.
return a * 10;
}
// ExecuteMethod2 함수
private static void ExecuteMethod2(int a)
{
// 파라미터에서 a의 값을 받으면 콘솔 출력한다.
Console.WriteLine(a);
}
// 실행 함수
static void Main(string[] args)
{
// 변수 선언
int a = 5;
// ExecuteMethod1 함수 호출
// 파라미터에 5를 집어넣으면 ret의 변수에 50의 반환 값이 대입된다.
int ret = ExecuteMethod1(a);
// 콘솔 출력
Console.WriteLine(ret);
// ExecuteMethod2 함수 호출
// 함수 안에서 콘솔 출력
ExecuteMethod2(a);
// 아무 키나 누르면 종료
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
}
위 소스에서 ExecuteMethod1 함수와 ExecuteMethod2 함수를 만들었습니다.
앞에 private와 static은 접근 제한자와 static 정적 타입을 설정하는 키워드인데 이것은 다른 글에서 조금 더 자세하게 설명하겠습니다.
그 외의 구조는 void와 int형의 반환형이 있습니다. void는 반환이 필요가 없다는 뜻입니다. 즉, ExecuteMethod2의 함수에서는 반환이 필요거 없습니다.
ExecuteMethod1의 함수에서는 반환형이 int형이기 때문에 함수 내에 return을 꼭 int 타입으로 반환을 해야합니다.
파라미터는 둘 다 int형을 받았습니다. 파라미터는 꼭 있어야 하는 필수 요소는 아니고 없어도 함수를 만들 수 있습니다.
Main 함수로 돌아오면 제가 ExecuteMethod1와 ExecuteMethod2를 사용했습니다.
두 함수다 파라미터를 요구하기 때문에 int형으로 된 변수를 넘깁니다. ExecuteMethod1의 경우는 반환 값이 int형이 있기 때문에 ret의 변수로 값을 받습니다.
ret를 콘솔 출력으로 확인해 보니 5의 값이 10배가 된 50이 된 것을 확인할 수 있습니다.
ExecuteMethod2함수에서 a의 변수를 넘겨서 콘솔 출력을 했습니다.
좀 더 함수의 파라미터를 복잡하게 사용해 보겠습니다.
using System;
namespace Example
{
class Program
{
// ExecuteMethod1 함수
// 파라미터 a를 참조하여 결과를 내보낼 수 있다.
private static int ExecuteMethod1(ref int a, int b)
{
// b의 값에 10을 곱한다.
b *= 10;
// a의 값에 100을 곱한다.
a *= 100;
// 결과 리턴
return b;
}
// ExecuteMethod2 함수
// 함수 내의 결과를 파라미터로 내보낼 수 있다.
private static void ExecuteMethod2(out int a)
{
a = 123;
}
// 실행 함수
static void Main(string[] args)
{
// 변수 선언
int a = 5;
int b = 10;
// ExecuteMethod1 함수 호출. 파라미터가 참조형(ref)이기 때문에 명시한다.
int ret = ExecuteMethod1(ref a, b);
// ExecuteMethod1의 반환 값 = 50 , 콘솔 출력
Console.WriteLine("ExecuteMethod1 return = {0}", ret);
// 콘솔 출력
Console.WriteLine("a = {0}", a);
Console.WriteLine("b = {0}", b);
// ExecuteMethod2 함수 호출. 파라미터가 출력형(out)이기 때문에 명시한다.
ExecuteMethod2(out b);
// 콘솔 출력
Console.WriteLine("b = {0}", b);
// 아무 키나 누르면 종료
Console.WriteLine("Press any key");
Console.ReadLine();
}
}
}
파라미터에 ref와 out의 키워드가 있습니다. ref은 함수 외부에서 변수를 끌어오는 것을 뜻합니다.
ExecuteMethod1 함수에서 ref를 사용한 a 파라미터는 함수 내에서 값을 수정을 하면 외부에서 선언된 a 변수에 값이 변합니다.
그러나 ref를 사용하지 않은 b 파라미터는 함수 내에서 값을 수정을 하더라도 외부의 변수는 영향이 없습니다.
함수에서 반환하는 값이 여러개 일 수도 있습니다. 그럴 때 함수 반환(return)만으로는 여러개의 값을 반환할 수 없습니다.
그래서 파라미터에 out 키워드를 사용해서 파라미터로 값을 반환 할 수도 있습니다.
using System;
namespace Example
{
class Program
{
// ExecuteMethod 함수
// params 키워드를 사용하면 파라미터는 가변으로 설정된다.
private static void ExecuteMethod(params string[] args)
{
// 가변 파라미터는 배열로 값을 받는다.
foreach (string arg in args)
{
// 콘솔 출력
Console.Write("{0} ", arg);
}
// 개행
Console.WriteLine();
}
// 실행 함수
static void Main(string[] args)
{
// 변수 선언
string a = "Hello world";
string b = "Test";
string c = "abc";
// ExecuteMethod 함수 호출
// 파라미터 a, b, c (3개)
ExecuteMethod(a, b, c);
// ExecuteMethod 함수 호출
// 파라미터 c, b ,a , "Good." (4개)
ExecuteMethod(c, b, a, "Good.");
// 아무 키나 누르면 종료
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
params의 키워드는 파라미터를 가변으로 만들 수 있습니다. 가변 파라미터란 파라미터의 개수가 정해지지 않은 뜻을 이야기합니다.
즉, ExecuteMethod의 파라미터에 3개를 넣을 수도 4개를 넣을 수도 있습니다.
ExecuteMethod 함수에서는 가변 파라미터를 배열로 받을 수 있습니다.
using System;
namespace Example
{
class Program
{
// ExecuteMethod 함수
private static int ExecuteMethod(int a)
{
// a가 1보다 크면
if (a > 1)
{
return a * ExecuteMethod(a - 1);
}
else
{
// a보다 작으면 1를 반환한다.
return 1;
}
}
// 실행 함수
static void Main(string[] args)
{
// ExecuteMethod(5)의 값은?
Console.WriteLine(ExecuteMethod(5));
// 아무 키나 누르면 종료
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
위는 ExecuteMethod함수 안에서 ExecuteMethod를 호출했습니다. 함수에서 자기 자신을 호출하는 재귀 호출입니다.
재귀 호출은 수학에서의 재귀적 호출과 같은 이야기입니다. 위 식은 f(x)=x*f(x)의 식과 같습니다.
f(5)=5*f(4)를 풀게되면 5*4*3*2*1(120)입니다.즉, 팩토리얼이 됩니다.
C#은 객체 지향 언어입니다. 이 객체 지향은 사실 클래스와 아주 밀접한 기능이 있는데, 그 중 클래스의 함수를 작성할 때 다형성의 기능이 있습니다.
C#의 객체 지향에 대해서는 다른 글에서 자세히 설명하고 여기서는 다형성에 대해 설명하겠습니다.
using System;
namespace Example
{
class Program
{
// ExecuteMethod 함수
private static void ExecuteMethod(int a)
{
Console.WriteLine("ExecuteMethod - int - " + a);
}
// ExecuteMethod 함수
private static void ExecuteMethod(string a)
{
Console.WriteLine("ExecuteMethod - string - " + a);
}
// 실행 함수
static void Main(string[] args)
{
// ExecuteMethod에서 파라미터 int형 함수 호출
ExecuteMethod(1);
// ExecuteMethod에서 파라미터 string형 함수 호출
ExecuteMethod("hello world");
// 아무 키나 누르면 종료
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
사실 다형성이라고 거창한 내용은 아닙니다. 같은 이름의 함수에서 파라미터 타입이 다른 것을 뜻합니다.
위 예제를 보시면 함수에 int타입을 넣는 것이랑 string타입을 넣는 것은 호출하는 함수가 다르고 결과도 다르게 나옵니다.
왜 이런 기능이 있는 지에 대해서는 클래스의 OOP의 특성을 알아야 합니다. 다른 글에서 자세히 설명하도록 하겠습니다.
링크 - 작성중
여기까지 C#의 함수(Method)와 오버로딩과 재귀 호출에 대한 글이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Study > C#' 카테고리의 다른 글
[C#] 12. 클래스 상속과 재정의(override)하는 방법과 override와 new의 차이 (2) | 2020.07.10 |
---|---|
[C#] 11. static과 접근 제한자 그리고 캡슐화 (1) | 2020.07.09 |
[C#] 10. 인스턴스 생성(new)과 메모리 할당(Stack 메모리와 Heap 메모리) 그리고 null (3) | 2020.07.07 |
[C#] 09. 클래스 생성하는 방법(생성자, 소멸자) (2) | 2020.07.02 |
[C#] 07. 배열과 리스트 (0) | 2020.06.30 |
[C#] 06. 제어문 (0) | 2020.06.29 |
[C#] 05. 형 변환(Cast)과 주석(Comment) (4) | 2020.06.26 |
[C#] 04. 연산자 (5) | 2020.06.24 |