메소드
C#에서는 기본적으로 선언과 함께 구현이 이루어져야 하며 메소드에 대해서 C++ 처럼 오버로딩 (overloading) 및 오버라이딩(overriding) 할 수 있다. 인자의 전달 방법에 있어서는 C++와 중요한 차이가 있다. C++에서는 인자의 형에 관계없이 기본적으로 call-by-value 방식으로 인수가 전달이 되며 call-by-reference로 전달할 경우는 별도로 지정을 해 주어야 한다. 하지만 C#에서는 인자 (또는 데이터)의 유형 (type)에 따라 전달 방식이 달라진다. C#에는 포인터형이 사리지고 value형과 reference형만 존재한다. [표 xx]에서 보는 바와 같이 value형인 경우는 call-by-value로 전달되며 reference형인 경우는 call-by-reference로 전달된다.
참조형 인자인 경우는 참조가 넘어가기 때문에 메소드 안에서 참조형 인자를 조작하면 원래의 데이터 (객체)가 조작이 된다. 하지만 값형 인자인 경우는 값이 복사가 되어 넘어 오기 때문에 값형 인자를 갖고 조작하면 복사본 자료가 조작되고 원본 데이터에는 아무런 변화가 없게 된다. 하지만 경우에 따라서는 값형의 데이터를 인자로 넘기면서 참조형처럼 동작시키고 싶은 경우들이 존재한다. 예를 들어, 메소드의 리턴 값으로 두 개 이상의 값을 넘기고 싶을 때, 하나는 메소드의 리턴값으로 넘기고 다른 하나는 참조형 형태로 넘길 수 있다. 이러한 경우에 아래의 예제 코드처럼 메소드 호출 부분과 메소드 인자 선언부에 값형 인자의 앞에 ref나 out 키워드를 추가로 붙여주면 된다.
using System;
class TestClass
{
static void Main()
{
int x,y;
TestClass ob;
x = 3; y = 0;
ob = new TestClass();
ob.func(ref x, ref y);
Console.WriteLine("x={0}, y={1}", x, y);
Console.ReadLine();
}
void func1(ref int p, ref int q)
{
q = p * p;
p = 2 * p;
}
}
필드와는 달리 메소드 내의 지역 변수들은 자동으로 초기화되지 않으며 초기화도지 않은 채 사용하면 컴파일 시 오류 메시지를 맞게 된다. 만약 위의 예제에서 y의 값을 0으로 초기화하지 않고 수행시키면 “할당되지 않은 'y' 지역 변수를 사용했습니다.”라는 메시지가 출력된다. 하지만 ref 키워드 대신에 out을 사용하면 컴파일 오류없이 수행이 된다. out 키워드는 초기화되지 않은 변수를 넘겨서 사용할 수 있다는 점을 제외하면 ref와 동일하다.
C#에서는 가변길이 인수도 선언할 수 있다. 메소드의 인수 목록 끝부분에 배열로 선언하고 가변길이임을 나타내기 위해 param 키워드를 추가로 붙여주면 된다. 아래의 예제 코드는 여러개의 long 형 값들을 받아 그들의 합을 반환하는 메소드를 정의한 것이다.
static long AddList(params long[ ] v) {
long total, i;
for (i = 0, total = 0; i < v.Length i++) total += v[i];
return total;
}
static void Main( ) {
long x = AddList(63,21,84);
}
이 외에, C++에서는 멤버함수를 const로 선언함으로써 그 멤버함수가 객체의 데이터 멤버를 고칠 수 없도록 할 수 있다. 하지만 C#에서는 이러한 기능이 제공되지 않는다. 또한, C#에서는 멤버함수 호출 시 해당 인수가 주어지지 않을 때 디폴트로 전달되는 디폴트 인자 (default argument)도 제공되지 않는다.
메소드도 static 키워드를 사용하여 정적 메소드로 선언할 수 있다. 알다시피, 정적 메소드는 객체 생성 없이도 수행 가능해야 하기 때문에 메소드 내에서 비정적 필드를 참조할 수 없다. 정적 함수는 클래스이름.정적함수의 형태로 호출한다. 정적 메소드는 주로 정적 필드의 값을 조회하거나 변경하는 메소드 구현 시 사용된다.