일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |
- 크로스오버
- 단 벌란
- 유로댄스
- 몰도바
- o-zone
- POP
- Arsenie Todiraş
- Windows DDK
- WinAPI
- Maksim
- 아르세니에 토디라슈
- 해외 여행
- Radu Sârbu
- input method editor
- API
- ime
- Romanian
- Euro-Dance
- 라두 스르부
- Jr
- Dan Balan
- 막심 므라비차
- Moldovan
- c언어
- 철도
- Disc O-Zone
- Windows API
- 루마니아어
- 일본 여행
- windowsAPI
- Today
- 204
- Total
- 1,073,377
(코딩캣) = "코딩"하는 고양이;
C# 기본 문법 – 대리자 편 1편. 대리자 본문
C# 기본 문법 – 대리자 편 1편. 대리자
컴파일러님, 이 코드는 고양이발로 작성되었습니다. 코딩집사 2011. 2. 14. 23:03C# 기본 문법 – 대리자 편
- 1편. 대리자 -
- by tapito
C#이 객체지향 언어이기는 하지만, 함수지향형 언어가 갖는 특징을 갖기도 합니다. 이를 테면, C 언어의 함수 포인터에 해당하는 기능이 C#에도 있다는 거죠. 오히려 C 언어의 함수 포인터보다 기능이 더 강화되었습니다. 이번 시리즈에서는 C#이 갖고 있는 3가지 기능. 대리자, 무명 메서드, 람다식에 대해 알아보겠습니다.
1. 대리자(Delegate)
모든 파생된 기법의 근원
C# 초기 버전부터 있던 기능입니다. C 언어의 함수 포인터를 그대로 차용한 거나 다름없죠. 메서드의 위치를 간직하고 있으면서 그 메서드를 대신 실행해 주는 역할을 합니다. 이게 왜 필요한가? 이렇게 이해하시면 간단합니다. 해당 메서드를 직접 호출 할 수 없는 경우, 예를 들면 외부 어셈블리에 있다거나, 그 메서드가 private라던가, 아니면 호출해야 하는 메서드가 런타임 도중 동적으로 바뀌는 경우 등.
그래서 바깥에서 이 함수를 직접 호출할 수 없을 때, 대리자에게 "야! 저기 국경너머 저 함수 보이지? 여기 매개변수 줄 테니까 넘어가서 실행 좀 하고 와라!" 내지는 "야! 대리자! 나 지금 귀찮으니까 저기 있는 함수 네가 대신 좀 실행시켜라!" 뭐 이런 뜻이라고 보면 됩니다. ㅎㅎ
그럼 대리자를 어떻게 사용하느냐? 예제를 한번 봅시다.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CsTest { class Program { delegate int DelegateMethod(int a, int b); // 이런 형식의 함수를 대신 호출해 주겠다의 의미입니다. static int Average(int a, int b) { return (int)((a + b) / 2); } static void Main(string[] args) { // Average 메서드를 직접 호출하는 대신 dm이라는 인스턴스를 통해 간접 호출합니다. DelegateMethod method = Average; int a, b; Console.Write("값 a를 입력하세여 >> "); a = int.Parse(Console.ReadLine()); Console.Write("\n"); Console.Write("값 b를 입력하세여 >> "); b = int.Parse(Console.ReadLine()); Console.Write("\n"); // 여기서 Average가 간접 호출 됩니다. Console.WriteLine("(a = {0})과 (b = {1})의 연산 결과는 {2}입니다.", a, b, method(a, b)); Console.WriteLine("끝."); Console.ReadLine(); } } }
실행 결과는 다음과 같습니다.
Average메서드를 직접 실행한 것과 method를 거쳐서 실행한 것의 결과는 같습니다. 그러나 내부적으로는 이런 차이가 있죠.
delegate를 이용한 경우 |
직접 실행한 경우 |
|
|
대리자의 작동 과정을 보았으니 이제 대리자의 선언과 실제 사용 부분을 볼까요? DelegateMethod는 이렇게 선언 되었습니다.
delegate int DelegateMethod(int a, int b); |
이 선언을 인간의 언어로 풀이하자면
int형 매개변수 2개를 받아서 int형으로 반환하는 함수 꼴을 DelegateMethod라고 이름 붙이겠다
이런 의미입니다. 즉 붕어빵으로 치면 붕어빵 틀을 만든 거죠. 이제 이 틀을 이용합니다.
DelegateMethod method = Average; |
method라는 대리자를 하나 만들고 여기에 Average라는 메서드를 채워 넣습니다.
이때 Average 메서드는 int형 매개변수를 2개 받고, 반환 값의 형태가 int이니까
위에서 선언했던 DelegateMethod로 이름 붙인 형식에 꼭 들어맞습니다.
따라서 별다른 에러 없이 Average 메서드 주소가 method 대리자 속에 폭 안깁니다.
이제 실행하는 일만 남았습니다.
Console.WriteLine("(a = {0})과 (b = {1})의 연산 결과는 {2}입니다.", a, b, method(a, b)); |
굵게 표시한 부분을 보면,
특이하게도 method 인스턴스 그 자체가 마치 함수처럼 호출이 되고 있습니다.
대리자이기에 가능한 거죠.
그리고 method는 Average의 메서드 정보를 품고 있으니까 Average를 실행하게 됩니다.
여기까지가 C의 것과 다를 바 없는 함수 포인터로서의 대리자였다면
이제부터는 C#(더 나아가서 .NET에만)에는 있는 아주 특별한 대리자의 성질을 보여드리겠습니다.
우선 예제부터 볼까요?
using System; |
결과는 다음과 같습니다.
C의 함수 포인터에는 없었던 기가 막힌 기능입니다.
바로 한 대리자가 여러 메서드를 끌어 안고 있다가 연쇄적으로 몽땅 실행할 수 있다는 거죠.
단, 이 때 조건은 반환 형이 void이어야 된다는 겁니다. 생각해 보세요.
여러 개의 메서드가 같은 매개변수를 받기는 했지만, 반환 값이 제각각 다르다면
그 다른 것 중에서 무엇을 선택해야 할 지가 .NET Framework의 입장에서는 모호합니다.
그렇기 때문에 여러 개의 메서드를 대리자 안에 넣고 싶다면 반드시 반환형이 void이어야 합니다.
위의 예제를 그림으로 표현하면 다음과 같습니다.
반대로 연쇄 호출 대상에서 메서드를 뺄 수도 있습니다.
using System; |
실행 결과는 다음과 같습니다.
네. 정말 재미있는 기능이죠.
그렇다면 이런 건 어떨까요?
using System; |
Method10이라는 메서드가 새로 만들어졌습니다.
그러나 이거는 method 대리자 입장에서는 자신에게 추가되지 않았기 때문에 '듣보잡'입니다.
그런데 중간에 method -= Method10; 이런 코드가 있습니다.
원래 갖고 있지 않던 것을 빼라는 거죠. 그러면 이때는 .NET Framework가 어떤 반응을 보일까요?
네. 그냥 잘 실행 됩니다. 없는 거를 빼라는 구문을 만나면
그냥 그것에 대해서는 아무 작업도 하지 않고 스므스하게 넘어가죠.
바로 이러한 대리자를 이용해 탄생한 개념이 '이벤트'입니다.
Windows API의 경우 '이벤트'는 윈도우 프로시져로 들어오는 WM_PAINT, WM_DESTROY 등의
메시지 상수에 따라 작업을 처리했지만 완전히 객체지향화 된 C#에서는 대리자를 활용해서
'이벤트'라는 독립된 구문을 하나 만들어버렸습니다.
예를 들어서 '창 클릭'이라는 동작에 대해 처리해야 할 것이 있다면,
'창 클릭'이라는 대리자를 특별히 이벤트라는 표시를 해서 선언하고
그 대리자에게 창 클릭 시 처리한 함수들을 몰아 넣는 거죠.
그러면 실제 창이 클릭 될 때, 대리자가 품고 있던 메서드들이 연쇄적으로 모두 실행 됩니다.
이벤트를 선언하는 방법은 너무나 간단합니다. 아래와 같은 선언을 클래스 안에다 넣으면 되죠.
public event DelegateMethod WindowClick; |
그리고 여느 대리자들과 마찬가지로 +=와 -= 연산자를 이용해 메서드를 몰아 넣을 수도,
부분 뺄 수도 있습니다. 실행하는 방법도 위와 동일합니다.
여기까지가 C# 초기 버전부터 있었던 대리자 기능에 대한 설명이었습니다.
다음에는 무명 메서드에 대해 설명하겠습니다. 읽어주셔서 감사합니다.
'Programming Language > C#' 카테고리의 다른 글
C#에서 Microsoft Excel 파일 다루는 방법 (2) | 2018.02.14 |
---|---|
C# 기본 문법 – 대리자 편 2편. 무명 메서드와 람다식 (18) | 2011.02.15 |
C# 기본 문법 – 대리자 편 1편. 대리자 (12) | 2011.02.14 |
-
씨샵인 2011.08.25 08:58 잘 보았습니다 !!
-
컴파일러님, 이 코드는 고양이발로 작성되었습니다. 코딩집사 2011.08.31 21:52 신고 감사합니다.
-
지나가던1인 2013.10.17 21:52 좋은 정보 너무 감사드립니다.
-
단골 2013.12.20 13:59 타 블로그 보다 더 쉽게 설명이 되었네요
각 코딩 마다 설명이 있어 많은 도움 되었읍니다 -
컴파일러님, 이 코드는 고양이발로 작성되었습니다. 코딩집사 2014.03.31 18:40 신고 그런가요 ㅋㅋ
-
Child 2014.03.17 13:30 여러 블로그랑 책을 봤는데
여기 글이 제일 깔끔하고 이해도 쉽고 가독성도 좋네요
수고하십니다 ^^ -
컴파일러님, 이 코드는 고양이발로 작성되었습니다. 코딩집사 2014.03.31 18:41 신고 감사합니다.
저는 이런게 좋더라고요. -
skip 2014.05.19 21:00 여러 곳 돌아다니다 여기서 c# Delegate 이해하고 갑니다. 수고하세요~ (_ _)
-
비전초보 2015.04.13 16:26 이해가 쏙쏙 되는 좋은 설명이였습니다.
감사합니다. -
delegate 2015.06.10 18:31 좋은 글 감사합니다.
많이 배워갑니다. -
c#초보 2015.10.31 11:00 설명 기가막히게 잘하시네요
감사합니다 이해가 잘 됐습니다 -
C# 2017.06.29 05:09 캬 명쾌한 설명 감사합니다