F.R.I.D.A.Y.

C# - 메서드에 대해서 본문

DEV/.Net

C# - 메서드에 대해서

F.R.I.D.A.Y. 2021. 5. 29. 00:22
반응형

일반 함수와 클래스 메서드


함수

 명령 단위라고 보면 될 것 같다.

 

선언

 C++과 전혀 다를 것이 없다. 반환형, 함수명, 매개변수 리스트 순으로 작성한다.

static void Test(){

}

 static을 붙인 이유라 함은, static을 붙이지 않으면 객체를 만들기 전까지 제대로 된 사용을 할 수 없다. 클래스 기반인 C#에선 C++과 달리 일반 함수로 사용하기 위해선 static 키워드를 붙여 이 함수가 메서드로 작성되지 않았음을 알려야 한다.[# 그렇다고 저렇게 작성한다고 해서 무조건 메서드가 아니란 소리가 아니다. 일반 함수처럼 사용하겠다는 뜻이지 메서드 중에서도 static 키워드를 붙인 메서드가 분명히 존재하고 또 만들 수 있다. 실질적으로 위에 보인 예시도 클래스 안에 들어가면 메서드의 일종이다. 객체를 참조하지 않는 메서드일 뿐이다.]

 

메서드

 클래스 내부에 존재하는 함수를 부르는 말로, OOP[# Object Oriented Programming] 개념을 만들기 위해 필요한 구성요소라 볼 수 있다.

 

선언

 기본적으로는 아래와 같이 선언을 한다.

class Test{
	public void log(){
    	System.Console.WriteLine("Test.log");
    }
}

 차례로 접근 제한자, 반환형, 메서드명, 파라미터 목록 순으로 작성한다.

 

 


인자 전달 방식

 함수나 메서드에 인자를 전달하는 방식은 몇가지가 존재한다.

 

값에 의한 전달

 메서드를 포함한 함수에서는 파라미터로 값을 전달받는다. 클래스 기반 데이터 타입이 아니라면 기본적으로는 값에 의한 전달을 한다. 즉, A에서 B로 a라는 데이터를 넘겼을 때, B에서 a를 가공한다고 A에서의 a가 변경되는게 아니라는 것이다.

static void test(int a)
{
	a += 5;
}

static void Main(string[] args)
{
	int a = 5;
    System.Console.WriteLine(a);
    test(a);
    System.Console.WriteLine(a);
}

 해당 코드를 실행 및 값을 확인하면 Main의 a는 test 함수 실행 뒤에도 여전히 5임을 알 수 있다.

 

레퍼런스에 의한 전달

 C++에선 한 번쯤 접해봤겠지만, C만 배운 사람은 레퍼런스에 의한 전달을 잘 모를 것이다. 레퍼런스에 의한 접근은 C/C++의 주소에 의한 접근[# 정확히는 주소에 의한 접근도 본래는 값에 의한 전달의 일종이다. 값으로 전달하지만 caller의 변수에 영향을 끼칠 수 있기 때문에 좀 더 세심하게 나눈 것이 주소에 의한 접근이다.]과는 약간 다르다. 레퍼런스 전달은 해당 공간을 건드릴 수 있는 새로운 변수라고 생각하면 편할지도 모르겠다.

 

 우리가 지명주소가 있고 도로명주소가 있는 것처럼, 서로 글로 쓰기는 다르지만 결국 같은 곳을 가리킨다. 하나의 별칭을 달아주는 것이라 생각하면 좋겠다.

 

 레퍼런스에 의한 전달은 ref 키워드를 사용한다.

static void test(ref int a)
{
	a += 5;
}

static void Main(string[] args)
{
	int a = 5;
    System.Console.WriteLine(a);
    test(ref a);
    System.Console.WriteLine(a);
}

 다음 코드를 실행하면 test 함수 실행 전후로 출력되는 값이 달라졌음을 알 수 있다. 기본적으로 값에 의한 전달을 수행하는 자료에 대해서는 ref 키워드를 통해 레퍼런스 전달을 수행하도록 할 수 있으며, 이미 레퍼런스 전달을 수행하는 자료형에 대해서도 동일한 작업을 한다.

 

강화된 레퍼런스 전달

 ref 키워드를 통해 레퍼런스 전달을 수행할 수 있지만, ref 키워드를 사용했을 때는 메서드 내부에서 해당 값에 대입을 무조건 수행해야하는 것은 아니다. 즉, 사용에 강제성이 없다.

 

 out 키워드는 메서드 내에서 무조건 한 번 이상 대입을 수행하도록 강제할 때 사용한다.

static void test(out int a)
{
	a = 5;
}

static void Main(string[] args)
{
	int a;
    test(out a);
    System.Console.WriteLine(a);
}

 out 키워드를 사용한 변수는 선언부에서의 초기화가 강제되지 않는다. 해당 초기화를 out으로 가져가는 메서드로 넘겨버리기 때문이다. 때문에 위 코드는 이상 없이 컴파일되고 실행되는데 아래의 경우는 살짝 다르다.

 

 아래 코드는 변수 선언부에서 초기화를 진행했으며, out 키워드를 통해 test 함수에서 a를 사용하고 있다

static void test(out int a)
{
	a += 5;
}

static void Main(string[] args)
{
	int a = 5;
    test(out a);
    System.Console.WriteLine(a);
}

 

 

 이미 초기화를 진행했기 때문에 이상이 없을 것이라 생각했다면 오산이다. out 키워드를 사용해 변수를 넘길 경우, 해당 변수의 초기화 여부를 메서드로 넘겨버린다. 즉, 선언부에서 제 아무리 초기화를 했다 하더라도 out 키워드로 접근을 한 test에서 사용 전 대입 과정을 거치지 않으면 컴파일 오류가 발생한다.

 예제의 복합대입 연산자 또한 똑같이 사용 전 대입 과정이 없었기 때문에 오류가 발생한다.

 

 

매개변수 옵션

 매개변수로 값을 전달하면서 사용할 수 있는 몇가지 옵션이 있다.

 

명시적으로 매개변수 전달하기

 일반적으로는 함수에서 구성한 파라미터 순서대로 값을 채워넣는다. 그러나 Named 파라미터 옵션을 사용하면 순서대로 값을 넣지 않아 된다.

static void Func(int iValue, string str);
// 정의 생략

static void Main(string[] args)
{
	Func(str:"Hello", iValue: 5);
}

 사용은 함수를 작성하면서 함께 작성한 매개변수 이름를 이용해 작성한다.

 

매개변수 기본값 설정

 많은 프로그래밍 언어에서 매개변수에 기본값을 설정하는 것을 제공한다.[# C++에서도 제공한다] 기본값을 사용하기 위해선 적용할 매개변수가 선언 끝에 있어야한다. 끝에 있다고 해서 기본값을 설정할 수 있는 매개변수가 하나뿐인 것은 아니고, 기본값을 설정한 매개 변수 사이에는 일반 매개변수가 존재할 수 없다.

static void Func1(int a, int b, int c = 1);
static void Func2(int a = 1, int b, int c = 1); // 오류
static void Func3(int a, int b = 1, int c = 1);

 예시처럼 기본값을 가지고 있는 매개변수는 우측에 몰려 있어야 한다.

 

 이 옵션과 함께 <명시적으로 매개변수 전달하기>를 이용하면 모든 매개 변수에 기본값을 달아놓고 명시적으로 전달하면 필요한 옵션만 활성화해 사용하는 함수도 만들 수 있을 것이다.

 

params 키워드

 먼저 params 키워드를 사용한 매개변수는 두 가지 조건을 충족해야한다.

  • 하나의 함수에선 params 키워드를 하나의 매개변수에만 사용할 수 있다.
  • params 키워드를 사용한 매개변수는 가장 마지막에 와야 한다.

 이 두가지 조건을 만족한 매개변수만이 정상적인 코드로 컴파일된다.

 

 params 키워드를 사용한 매개변수는 꼭 일차원 배열로 전달이 된다. 때문에 함수에서 선언하고 사용할 때는 일차원 배열처럼 작성하고 이용해야한다. 그러나 값을 넘길 때는 일차원 배열이 아니다.

static void Func1(params int[] args);
...


Func1(1,2,3,4,5,6,7,8);

 매개변수의 자료형은 int[]이지만, 실제 함수 호출부에서는 int[]이 아니라 int 타입의 자료를 여러 개 놓았을 뿐이다. 즉, int[] 타입으로 매개변수를 설정했다고 해서 System.Array 자료형으로 넘겨주지 않아도 된다는 말이다. params 키워드를 사용한 매개변수는 가변길이 매개변수라고 부를 수 있겠다.

 

# index

728x90
반응형

'DEV > .Net' 카테고리의 다른 글

C# - 접근제한자  (0) 2021.05.30
C# - 연산자 오버로딩  (0) 2021.05.29
C# - 구조체와 클래스  (0) 2021.05.28
C# - namespace(네임스페이스)  (0) 2021.05.28
C# - 예외 처리  (0) 2021.05.27
Comments