[C# 강좌]이벤트의 object sender의 파라미터의 이해

공부/C#  2015.01.13 22:45


안녕하세요 명월입니다.
이번 포스팅에서는 C#에서 이벤트를 생성할 때마다 따라 붙는 object sender 파라미터에 대해 알아보겠습니다.
각 컨트롤 단에서 이벤트를 선언하다보면 object sender와 각 이벤트의 EventArg 값이 파라미터에 붙는 것을 알 수 있습니다. EventArgs는 각 이벤트의 이벤트 값을 나타내는 것으로 잘 알고 있습니다.
[C# 강좌 14장] 이벤트 - http://nowonbun.tistory.com/120
[C# 강좌]이벤트 - 보강 - http://nowonbun.tistory.com/228

위의 이벤트 강좌를 보면 알 수 있을지는 모르겠지만 가장 쉬운 예로는 마우스 클릭 이벤트를 보면 알기 쉽습니다.


MouseDown 이벤트 안의 MouseEvenArgs 값에 발생할 당시의 마우스 좌표, 마우스 왼쪽 클릭인지 오른쪽 클릭인지의 데이터가 담겨져 있습니다.

그럼 본래의 목적인 obecjt sender의 값에는 무엇이 있는지 확인 해 보면 이벤트가 발생된 주체의 클래스가 담겨져 있습니다.
위 사진의 예를 들면 현재 Load, Click, MouseDown이벤트 세게를 등록을 하였는데 각 이벤트가 불려질 때의 sender 값에는 form클래스의 주소가 담겨져 있습니다.



위 결과값을 보면 해쉬값(메모리 주소)이 같은 것을 확인 할 수 있습니다.
즉 (Form)으로 강제 Recasting 후에 사용 가능하다는 의미이지요.
그러면 여기서 또 하나의 궁금한 점이 생깁니다. this로 하면 될걸 번거롭게 저런 파라미터를 만들었느냐 입니다.



첫번째는 캡슐화 때문입니다. 원래 C++를 경험해 본 유저라며는 어느정도 눈치를 채시겠지만 C++에서의 이벤트는 Java,C#에서의 이벤트와 개념이 약간 다름니다. 모든 이벤트는 메시지큐에서 이루어지고 그곳에서 값을 던지게 되어있습니다. C#은 C++보다는 객체지향이 조금 더 완전한 형태이기에 Form1이란 클래스는 Form을 상속받고 그 안에서 이벤트를 부르는 게 가능하나 C++에서는 그렇게 해도 안되는 것은 아니지만 소스관리가 엉망이 되고 사수한테 욕 한 사발 먹겠지요…
즉 Form의 이벤트는 내부에서 불리는게 아니라 외부에서 불려야 맞는 것입니다. 내부에서는 이벤트를 선언하는게 아니라 OnLoad처럼 Override함수를 사용해야 조금은 정확한 소스가 되겠습니다.
즉 외부에서Form이라는 클래스를 선언하고 이벤트를 부를 때 그 이벤트의 클래스 값을 무엇인지 또 하나하나 따로 넘길 필요없이 Object의 값으로 받으면 소스가 깔끔하게 보이겠죠

조금더 알기쉬운 예입니다.



Form 에다가는 Button 클래스를 상속받은 ExButton 두개를 선언에서 만들었습니다.
그리고 이벤트는 같은 것을 가르키게 만들었구요. 결과는 Console 창에 나오는 것처럼 각기의 Button값을 받아와서 Text값을 뿌려주고 있네요…
조금 설명이 어려웠다고 생각되나 이해가 되지 않는 부분이 있으면 질문 댓글을 남겨주세요.

evnetObject.zip




댓글 2개가 달렸습니다.
댓글쓰기
  1. Gs
    2016.02.16 15:03 신고 |  수정/삭제  댓글쓰기

    질문이 있습니다.
    제가 다루고있는 소스중에.
    버튼 클릭 이벤트에
    Button btn = (Button)sender; 이런식으로 나와있습니다.
    (참고로 버튼 2개가 있는데 버튼 2개 모두 똑같은 클릭 이벤트를 쓰고 있습니다.)
    그래서 sender가 먼지 궁금하여 여기까지 왔는데요
    일단 sender가 Form클래스의 주소가 담겨있다는건 알겠는데
    그 의미만 조금 알겠다뿐이지 sender를 정확히 왜쓰는지 모르겠어서
    질문 드립니다.

    • 明月 v명월v
      2016.03.04 10:09 신고 |  수정/삭제

      답변이 늦었네요.... 이벤트에 sender가 있는 이유는 이벤트를 발생한 객체를 가져오기 위함입니다..
      클래스를 구성할 때 물론 Button은 전역 변수를 사용하기 때문에 직접 받아서 사용해도 무방하지만.. 코드의 가독성을 위해선 그런 방법은 사용하지 않는 편이 좋습니다... 전역변수의 의미는 함수에서 끌어쓰겠다의 의미보다는 struct의 의미로써 클래스의 메모리 사이클의미로 사용하시는 편이... 나중을 위해 좋습니다.
      그럼 함수는 어떻게 짜는 게 좋냐고 하면 확실한 Input Output을 지정하여 어떠한 값을 넣으면 어떤값이 나온다라는 형식의 함수를 작성하셔야 후에 코드 관리가 쉬우실 껍니다..
      그런 의미로 sender는 이벤트의 재사용시 객체를 받는 역할을 하는 겁니다.
      그리고 쓰다가 생각난 건데 또 하나의 의미는 Form객체 안에서 이벤트를 사용하면 상관없겠지만 다른 클래스에서 이벤트를 끌어온다고 하면 OOP의 캡슐화로 button 객체를 참조할 수 없겠죠?? 그럴 때를 위해서도 사용하겠네요...