본문 바로가기

.NET/C#

[C#] 확장 메서드를 사용해 메서드 호출을 간결하게 하기

C#에는 확장 메서드 기능이 있다.

 

어떤 타입에 대해 클래스 외부에서 해당 클래스의 멤버 메서드를 추가로 구현하는 것이라고 보면 이해하기 쉽다.

(엄밀히 따지면 멤버 메서드는 아니다. private 멤버에는 접근할 수 없기 때문이다.)

 

Column이 번호, 이름, 학번으로 구성된 ListView 컨트롤에 아이템을 추가하는 방법은 다음과 같다.

var item = new ListViewItem(listView1.Items.Count.ToString());
item.SubItems.Add("홍길동");
item.SubItems.Add("12345678");
listView1.Items.Add(item);

 

그러나 매번 위 과정을 적기에는 생산성이 떨어지므로 아래와 같이 아이템을 추가하는 과정을 하나의 메서드로 만든다.

void AddStudent(ListView listView, string name, string studentNumber)
{
	var item = new ListViewItem(listView.Items.Count.ToString());
	item.SubItems.Add(name);
	item.SubItems.Add(studentNumber);
	listView.Items.Add(item);
}

 

그럼 다음부터는 아이템을 추가하기 위해 이렇게 호출할 수 있다.

AddStudent(listView1, "홍길동", "12345678");

 

확장 메서드를 사용하면 위 과정을 더 간단하게 줄일 수 있다.

백문이 불여일견이라고 한 번 보자.

static class Util
{
	static void Add(this ListView listView, string name, string studentNumber)
	{
		var item = new ListViewItem(listView.Items.Count.ToString());
		item.SubItems.Add(name);
		item.SubItems.Add(studentNumber);
		listView.Items.Add(item);
	}
}

 

뭐가 다르죠?

 

언뜻 보기에는 첫 번째 매개변수 앞에 this 키워드가 붙은 것을 제외하면 위에서 만든 AddStudent() 메서드와 크게 다를 것이 없어 보인다. 하지만 가장 크게 달라지는 부분은 메서드의 호출 방법이다.

AddStudent(listView1, "홍길동", "12345678");	// 기존 메서드 호출 방법

Util.Add(listView1, "홍길동", "12345678");	// 일반적인 정적 메서드 호출 방법

listView1.Add("홍길동", "12345678");		// 확장 메서드 호출 방법

 

!!!!!!!!

 

그렇다. 확장 메서드는 마치 ListView 클래스의 멤버 메서드인 것 마냥 호출이 가능하다.

확장 메서드는 따지고 보면 정적 메서드에 속하기 때문에 2번째 줄처럼 일반적인 정적 메서드 호출 방식으로도 호출이 가능하다. 따라서 동일한 이름, 매개변수를 가지는 메서드가 존재하여 명시적으로 구분할 필요가 있는 경우 2번째 줄처럼 호출할 수도 있다.

 

조금 더 응용하면 아래와 같은 플레이도 가능하다.

static class Util
{
	// ListView의 index 위치에서 아이템을 삭제하고, 삭제한 아이템을 반환합니다.
	static ListViewItem RemoveAt(this ListView listView, int index)
	{
		if(0 <= index && index < listView.Items.Count) 
		{
			item = listView.Items[index];
			listView.Items.RemoveAt(index);
			return item;
		}
		else return null;
	}
}

ListView에서 아이템을 꺼내고, 꺼낸 아이템을 ListView에서 삭제하는 동작을 확장 메서드로 구현하였다.

 


주의점

코드를 보면 알겠지만 확장 메서드를 생성할 때는 다음과 같은 규칙을 따라야 한다. 아래 중 하나라도 성립되지 않으면 컴파일 오류가 발생한다.

1. 정적 메서드여야 한다.

2. 정적 클래스에 속해야 한다.

3. 속한 정적 클래스가 다른 클래스의 내부 클래스가 아닌 최상위 클래스여야 한다.

 

특히 중요한 것은 2번으로, 위 예제들처럼 확장 메서드를 위한 Util, Extensions 등의 이름으로 정적 클래스를 하나 별도로 생성해서 필요한 확장 메서드를 한 곳에 모아 두는 것도 좋은 방법이라고 할 수 있겠다.

 

또한 위에서 한 번 언급했지만 확장 메서드는 멤버 메서드처럼 호출할 수 있는 메서드일 뿐 실제 멤버 메서드는 아니기 때문에 당연히 private으로 선언된 멤버에는 접근이 불가능하다. 가령 아래와 같은 접근은 불가능하다는 뜻이다.

static class Util
{
	static void SetDoubleBuffered(this ListView listView)
	{
		listView.DoubleBuffered = true;	// 컴파일 오류! 보호 수준 때문에 ListView.DoubleBuffered 속성에 액세스 불가
	}
}

 

'.NET > C#' 카테고리의 다른 글

[C#] using 구문 사용법  (0) 2021.07.23
[C#] delegate와 delegate 체인  (0) 2021.07.20
[C#] 소켓 연결 시도에 타임아웃 넣기  (0) 2021.07.14
[C#] as, is 키워드 사용법  (0) 2021.07.14
[C#] 문자열 보간 기능  (0) 2021.07.14