"null"참조 (즉, 구독자가없는 이벤트)에 대한 확장 메서드를 호출하는 것이 악한가요?
악하거나 악하지 않습니까?
public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
if (handler != null)
{
handler(sender, args);
}
}
// Usage:
MyButtonClicked.Raise(this, EventArgs.Empty);
// This works too! Evil?
EventHandler handler = null;
handler.Raise(this, EVentArgs.Empty);
확장 메서드의 특성으로 인해 MyButtonClicked가 null 인 경우 MyButtonClicked.Raise는 NullReferenceException을 throw하지 않습니다. (예 : MyButtonClicked 이벤트에 대한 리스너가 없습니다).
악한가요?
사악하지 않습니다. 이벤트가 기본적으로 이런 식으로 작동하기를 바랍니다. 구독자가없는 이벤트가 null 인 이유를 누군가 설명 할 수 있습니까?
언제든지 다음과 같이 이벤트를 선언 할 수 있습니다 (권장하지 않음).
public event EventHandler<EventArgs> OnClicked = delegate { };
이렇게하면 호출 할 때 할당 된 것이 있으므로 널 포인터 예외가 발생하지 않습니다.
아마도 C # 3.0에서 delegate 키워드를 제거 할 수 있습니다.
사용하는 것을 잊지 마십시오. 그렇지 [MethodImpl(MethodImplOptions.NoInlining)]
않으면 스레드로부터 안전하지 않을 수 있습니다.
(오래 전에 그것을 읽고, 그것을 기억하고, 검색하고 http://blog.quantumbitdesigns.com/tag/events/ 찾았습니다 )
자바 배경에서 왔기 때문에 이것은 항상 나에게 이상하게 보였습니다. 이벤트를 듣는 사람이 완벽하게 타당하다고 생각하지 않습니다. 특히 리스너가 동적으로 추가 및 제거 될 때.
나에게 이것은 사람들이 매번 null을 확인하는 것을 모르거나 잊어 버릴 때 버그를 일으키는 C #의 문제 중 하나 인 것 같습니다.
이 구현 세부 사항을 숨기는 것은 매번 null을 확인하는 가독성에 도움이되지 않으므로 좋은 계획으로 보입니다. 나는 MSFTs가 아무도 듣고 있지 않으면 이벤트를 구성하지 않으면 성능이 향상된다고 말할 것이라고 확신하지만 대부분의 비즈니스 코드에서 무의미한 널 포인터 예외 / 가독성 감소로 인해 훨씬 더 중요합니다.
또한이 두 가지 메서드를 클래스에 추가합니다.
public static void Raise(this EventHandler handler, object sender)
{
Raise(handler, sender, EventArgs.Empty);
}
public static void Raise<TA>(this EventHandler<TA> handler, object sender, TA args)
where TA : EventArgs
{
if (handler != null)
{
handler(sender, args);
}
}
왜 악할까요?
목적은 명확합니다. MyButtonClicked 이벤트를 발생시킵니다.
함수 호출 오버 헤드를 추가하지만 .NET에서는 최적화되거나 어쨌든 매우 빠릅니다.
약간 사소하지만 C #에 대한 가장 큰 불만을 해결합니다.
전반적으로 나는 그것이 환상적인 아이디어라고 생각하며 아마도 그것을 훔칠 것입니다.
나는 그것이 나쁘다고 말하지는 않겠지 만, 당신의 확장 방법이
protected virtual OnSomeEvent(EventArgs e){ }
패턴과 상속을 통해 확장 성을 처리하는 방법. 모든 하위 클래스가 메서드를 재정의하는 대신 이벤트를 처리한다고 가정합니까?
내가 그것을 악 이라고 설명하지는 않겠지 만 , 불필요한 오버 헤드를 추가하기 때문에 여전히 부정적인 의미가 있습니다.
전화 할 때
myEvent.Raise(this, new EventArgs());
the object EventArgs is initialized in all situations, even if no-one subscribed to myEvent.
When using
if (myEvent!= null) {
myEvent(this, new EventArgs());
}
EventArgs is only initialized if someone subscribed to myEvent.
Throwing an exception when there are no handlers is not really preferable by the most. If it does not have an handlers it is better to be empty rather than null.
'program story' 카테고리의 다른 글
일반적인 Task.WaitAll이 있습니까? (0) | 2020.12.09 |
---|---|
AnkhSVN 대 VisualSVN (0) | 2020.12.09 |
"라틴"에서 지원하는 언어와 Google 웹 글꼴의 글꼴에서 "라틴 확장"글리프? (0) | 2020.12.09 |
ggplot2에서 facet_wrap ()과 facet_grid ()의 차이점은 무엇입니까? (0) | 2020.12.09 |
C17이란 무엇이며 언어가 어떻게 변경 되었습니까? (0) | 2020.12.09 |