.NET에서 이벤트에 대한 표준 패턴이 있습니다. 그들은 EventArgs
에서 파생되어야하는 두 번째 매개 변수에서 sender라는 일반 객체와 실제 "페이로드"를 취하는 delegate
유형을 사용합니다..NET에서 표준 EventHandler 패턴을 버리면 무엇이 손실됩니까?
EventArgs
에서 파생 된 두 번째 매개 변수에 대한 이론적 근거는 매우 명확합니다 (.NET Framework Standard Library Annotated Reference 참조). 소프트웨어가 발전함에 따라 이벤트 싱크와 소스 간의 바이너리 호환성을 보장하기위한 것입니다. 모든 이벤트에 대해 하나의 인수 만 있더라도 해당 인수가 포함 된 단일 속성을 갖는 사용자 정의 이벤트 인수 클래스를 파생하므로 기존 클라이언트 코드를 손상시키지 않고 향후 버전의 페이로드에 더 많은 속성을 추가 할 수 있습니다 . 독립적으로 개발 된 구성 요소의 생태계에서 매우 중요합니다.
하지만 제로 인수에 대해서도 마찬가지입니다. 즉, 첫 번째 버전에서 인수가없는 이벤트가 있고 다음과 같이 쓰는 경우를 의미합니다.
public event EventHandler Click;
... 그러면 잘못하고 있습니다. 나는 그것의 페이로드로 새로운 클래스에 미래의 대리자 형식을 변경하는 경우 :
public class ClickEventArgs : EventArgs { ...
을 ... 나는 나의 고객과의 바이너리 호환성을 깰 것입니다. 클라이언트는 EventHandler
걸리는 내부 메서드 add_Click
의 특정 오버로드에 바인딩되고, 위임 유형을 변경하면 해당 오버로드를 찾을 수 없으므로 MissingMethodException
이 있습니다.
좋아요, 그렇다면 편리한 일반 버전을 사용하면 어떨까요?
public EventHandler<EventArgs> Click;
없음
, 여전히 잘못EventHandler<ClickEventArgs>
가
EventHandler<EventArgs>
하지 않기 때문에.
EventArgs
의 혜택을 얻으려면 에이 그대로있는 그대로 사용하는 것이 좋습니다. 당신이하지 않으면, 당신도 그것을 사용하지 않을 수 있습니다 (그것은 나에게 보인다).
그러면 첫 번째 인수 인 sender
이 있습니다. 나는 신성하지 않은 결합을위한 조리법을 좋아하는 것 같습니다. 이벤트 발생은 기본적으로 함수 호출입니다. 함수는 일반적으로 말하자면 스택을 파헤쳐 호출자가 누구인지 알아 내고 그에 따라 행동을 조정할 수있는 능력이 있어야합니까? 우리는 인터페이스가 이렇게 보이도록 명령해야합니까?
public interface IFoo
{
void Bar(object caller, int actualArg1, ...);
}
는 Bar
의 구현은 caller
이 누구인지 알고 할 수 있습니다, 그래서 그들은 추가 정보를 조회 할 수 있습니다! 네가 지금 엿먹 으리라 믿어. 왜 이벤트를 위해 다른해야합니까?
그럼에도 불구하고 내가 선언 한 모든 이벤트에 대해 독립형 애플리케이션을 만드는 데 어려움을 겪을 준비가 되었더라도 EventArgs
을 사용하는 동안 내 가치가있게 만들었습니다. 확실히 개체 발신자 인수를 삭제하는 것이 좋습니다. .
Studio의 자동 완성 기능을 사용하면 이벤트에 사용하는 것을 위임 상관하지 않는 것 같습니다 시각 - 당신은 입력 할 수 있습니다 +=
[공간, 돌아 히트]를 선택하고 당신을위한 핸들러 방법을 씁니다이 될 일이 무엇이든 위임 경기 .
그렇다면 표준 패턴에서 벗어나서 어떤 가치를 잃을까요?
보너스 질문으로 C#/CLR 4.0은 대리자의 반공 변을 통해이 변경 작업을 수행합니까? 나는 이것을 조사하려고 시도했지만 another problem을 누르십시오. 나는 원래 그 질문의이 부분을 다른 질문에 포함 시켰지만 거기에서 혼란을 야기했다. 그리고 ... 세 가지 질문의 총에이를 분할하는 것이 조금 많은 것 같다
업데이트 :
내가이 모든 문제에 대한 contravariance의 효과에 대해 궁금해하는 것이 옳다고 밝혀!
noted elsewhere과 같이 새로운 컴파일러 규칙은 런타임에 불어 나오는 유형 시스템에 구멍을 남깁니다. EventHandler<T>
을 Action<T>
과 다르게 정의하면 구멍이 효과적으로 막혔습니다.
이벤트의 경우 해당 유형 구멍을 피하려면 Action<T>
을 사용하지 않아야합니다. 그렇다고해서 EventHandler<TEventArgs>
을 사용해야한다는 의미는 아닙니다. 일반 대리자 형식을 사용하는 경우 반 경쟁이 활성화 된 형식을 선택하지 말아야합니다.
downvoter에서 이유를 듣고 싶습니다. –
나는 어떤 방법으로도 투표하지는 않았지만, 여기에 하나 이상의 질문이 적어도 있기 때문에 downvote가 의심된다. 나는 정말로 모든 것을 나 자신으로 다루려고하고 싶지는 않지만, (지금 당장 그것에 대해 쓰고있는 것처럼) 분산 측면을 보아서 기쁘다. 당신이 밖으로을 재현 할 수있는 짧지 만 완전한 케이스 별도의 문제로 실행시 실패에 이르게 비트를 분리 할 수 있다면, 나는 –
가 –