이벤트를 선언하는 선호되는 방법


14

.NET 이벤트 모델에 대한 이해에 상당히 만족합니다. 시스템의 작은 뉘앙스를 오해하고 있다고 생각합니다.

클래스에 이벤트를 넣기 시작했을 때 표준 방식을 사용합니다.

public event EventHandler<MyEventArgs> MyEvent;

즉, 이벤트를 구독하려면 다음과 같은 방법이 필요합니다.

void HandleThatEvent(object sender, MyEventArgs args){...}

어느 것이 좋았지 만 발신자에 대해서는 거의 신경 쓰지 않을 것이므로 많은 메소드 서명이 부풀어 오른 것으로 나타났습니다.

그래서 나는 자신의 델리게이트 유형을 선언하는 것으로 전환

public delegate void MyEventHandler(SomeClass argument);

어느 것이 혼란스럽지 만 처리기를 작성할 때 작은 문제가 생겼습니다.

eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)

그래서 나는 대의원의 선언으로 돌아가서 되돌아 가서 글을 쓰거나 컴파일하고 말을 기다립니다.

이제 대신, 또는 템플릿에 맞는 것을 사용 Action하고 Action<T>있습니다.

public event Action<SomeClass> MyEvent;

이벤트 위로 마우스를 가져 가면 예상되는 매개 변수를 알 수 있습니다.

결국 내 질문 : C #에서 이벤트를 선언하는 가장 좋은 방법이 있습니까? 다시 돌아 가야합니까 EventHandler<T>, 아니면 Action<T>괜찮습니까?


핸들러가 이벤트를 발생시키는 위치에 로컬로 복사되어 있는지 확인하는 것을 잊지 마십시오. 스레드 안전을 위해 항상 수행하십시오.
Snoop

캡슐화 된 코드로 자신 만의 스마트하고 의미 있고 마른 타입 안전 이벤트를 작성할 수 있지만 게시하는 모든 항목은 표준 패턴을 따라야합니다.
Martin Maat

답변:


8

간단한 내부 이벤트 처리의 경우, 단순히 사용하는 사람들이 있습니다 Action또는 Action<T>당신이 제안하는대로. 나중에 클래스 나 이벤트를 노출하고 싶을 때를 알지 못하기 때문에 발신자를 포함하여 표준 패턴을 사용하는 경향이 있습니다. 공개.

이벤트 처리 시그니처가 간단한 시나리오보다 약간 무겁지만 시간이 지남에 따라 추가 이벤트 인수가 필요할 수 있으므로 증분 마이그레이션을 처리하도록 잘 설계되어 있습니다. 전반적으로, 나는 표준 패턴을 고수 할 것입니다. 특히 언급했듯이 적절한 IntelliSense 지원 만받을 수 있기 때문입니다.

가치있는 것을 위해, 나는 이것에 약간의 시간을 투자하고 다른 이벤트 처리 패턴을 생각해 냈습니다 . . 여기서의 목표는 발신자를 제거하는 TSender것이 아니라 약한 유형으로 대신 일반 유형으로 강하게 입력하는 것입니다 System.Object. 잘 작동합니다. 그러나 이렇게하면 IntelliSense 지원이 손실되므로 불행히도 절충이 발생합니다.

전반적으로, 나는 표준 패턴을 고수 할 것이지만, 잠재적으로 더 좋은 방법을 생각하는 것은 흥미 롭습니다.


당신의 SO 질문을 지적 해 주셔서 감사합니다. 이것은 매우 흥미 롭다. 발신자가 필수 인 이유를 여전히 이해하지 못합니다. 대부분의 경우 보낸 사람을 신경 쓰지 않습니다. 임의의 MS 규칙입니까?
Matt Ellen

물론, 당신은 당신이 원하는대로 당신의 대표를 선언 할 수 있습니다. 보낸 사람을 항상 포함시키는 것이 .NET 정책이며, 그 점에서 완전히 나쁜 생각은 아닙니다.
Neil

@ Neil : 때로는 유용하게 사용된다는 것을 알고 있지만 항상 그렇게하는 정책을 얻지 못합니다. 특히 MS는 이벤트를 진행하는 것이 좋습니다. 이벤트에서 정말 좋아하는 것 중 하나는 클래스를 분리하는 기능입니다. 객체를 포함 시키면 다시 연결됩니다. 그것이 단지 CLS 준수 일이라면 나는 그걸로 살 수 있습니다.
Matt Ellen

sender 객체를 사용하는 경우에만 다시 연결되며, 그렇지 않으면 sender를 사용하지 않기 때문에 sender의 값으로 무엇을 넣든 상관 없습니다. 종속성은 종속성이 필요한 경우에만 존재합니다. 나는 당신이 어디에서 왔는지 알며, 지구상의 모든 서버에서 모든 코드에서 객체 발신자가 사라지면 밤새 머물지 않을 것입니다.
Neil

예, 정말로 원한다면 발신자로 'null'을 보낼 수 있습니다. 그러나 발신자를 포함시킴으로써 이벤트 핸들러 자체가 원할 경우 구독을 취소 할 수 있습니다. 그러나 전반적으로 이벤트의 출처를 아는 것이 일반적으로 매우 중요하다고 말하고 싶습니다.
Mike Rosenblum
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.