Programing

이벤트 액션 <> vs 이벤트 EventHandler <>

lottogame 2020. 6. 30. 08:23
반응형

이벤트 액션 <> vs 이벤트 EventHandler <>


선언 사이에 다른 거기에 event Action<>하고 event EventHandler<>.

어떤 객체가 실제로 이벤트를 발생시키는 것이 중요하지 않다고 가정합니다.

예를 들면 다음과 같습니다.

public event Action<bool, int, Blah> DiagnosticsEvent;

vs

public event EventHandler<DiagnosticsArgs> DiagnosticsEvent;

class DiagnosticsArgs : EventArgs
{
    public DiagnosticsArgs(bool b, int i, Blah bl)
    {...}
    ...
}

두 경우 모두 사용법이 거의 동일합니다.

obj.DiagnosticsEvent += HandleDiagnosticsEvent;

event EventHandler<>패턴 에 대해 싫어하는 몇 가지 사항이 있습니다 .

  • EventArgs에서 파생 된 추가 유형 선언
  • 객체 소스의 강제 전달 – 종종 아무도 신경 쓰지 않음

코드가 많을수록 분명한 이점없이 유지해야 할 코드가 많아집니다.

결과적으로, 나는 선호한다 event Action<>

그러나 Action <>에 유형 인수가 너무 많은 경우에만 추가 클래스가 필요합니다.


가장 큰 차이점은 Action<>이벤트 를 사용 하면 시스템의 다른 이벤트의 디자인 패턴을 따르지 않는다는 것입니다. 이는 단점을 고려할 것입니다.

지배적 인 디자인 패턴 (동일성의 힘을 제외하고)의 한 가지 단점 EventArgs은 이벤트의 서명을 변경하지 않고도 새로운 속성으로 객체를 확장 할 수 있다는 것 입니다. 를 사용하면 여전히 가능 Action<SomeClassWithProperties>하지만 실제로는 일반적인 접근 방식을 사용하지 않는 것이 중요하지 않습니다.


이전 답변 중 일부를 기반으로 답변을 세 가지 영역으로 나누겠습니다.

먼저, Action<T1, T2, T2... >파생 클래스를 사용하는 데 대한 물리적 제한 EventArgs있습니다. 세 가지가 있습니다. 첫째, 매개 변수의 수 또는 유형을 변경하는 경우 구독하는 모든 메소드를 새 패턴에 맞게 변경해야합니다. 제 3 자 어셈블리가 사용할 공개 이벤트이고 이벤트 인수가 변경 될 가능성이있는 경우, 일관성을 위해 이벤트 인수에서 파생 된 사용자 정의 클래스를 사용해야하는 이유입니다. 사용 Action<MyCustomClass>하여,) 둘째 Action<T1, T2, T2... >는 예를 들어 처리 된 속성 객체의 어떤 종류 (하지 않는 한 동작과 함께 전달되는) 호출 방법 피드백 BACK을 통과하지 못할 것입니다. 세 번째는 3을 전달하는 그렇다면, 당신은 매개 변수를 명명되지 않은이 bool'는 S int, 두stringDateTime, 당신은 그 값들의 의미가 무엇인지 전혀 모른다. 참고로 "여전히 이벤트를 안전하게 사용하는 동안이 이벤트를 안전하게 실행"할 수 있습니다 Action<T1, T2, T2... >.

둘째, 일관성 함의. 이미 작업중인 대형 시스템이있는 경우, 정당한 이유가없는 한 시스템의 나머지 부분이 설계된 방식을 따르는 것이 거의 항상 좋습니다. 유지 관리해야하는 이벤트에 공개적으로 직면 한 경우 파생 클래스를 대체하는 기능이 중요 할 수 있습니다. 명심하십시오.

세 번째로, 실제 연습에서는 개인적으로 상호 작용해야하는 속성 변경 (특히 서로 상호 작용하는 뷰 모델로 MVVM을 수행 할 때) 또는 이벤트가있는 위치에 대해 많은 일회성 이벤트를 생성하는 경향이 있음을 개인적으로 발견했습니다. 단일 매개 변수. 대부분의 경우 이러한 이벤트는 public event Action<[classtype], bool> [PropertyName]Changed;또는 형식입니다 public event Action SomethingHappened;. 이 경우 두 가지 이점이 있습니다. 먼저 발급 클래스의 유형을 얻습니다. 경우 MyClass선언하고 이벤트를 트리거하는 유일한 클래스, 난의 명시 적 인스턴스를 얻을 MyClass이벤트 핸들러에 대한 작업. 둘째, 속성 변경 이벤트와 같은 간단한 이벤트의 경우 매개 변수의 의미가 명확하고 이벤트 처리기 이름으로 명시되어 있으므로 이러한 종류의 이벤트에 대해 수많은 클래스를 만들 필요가 없습니다.


대부분의 경우 패턴을 따릅니다. 나는 그것에서 이탈,하지만 아주 드물게, 특정 이유로. 필자의 경우 가장 큰 문제는 아마도 여전히을 사용하여 Action<SomeObjectType>나중에 추가 속성을 추가하고 가끔 2 웨이 속성 (생각 Handled또는 다른 피드백 이벤트를 사용할 수 있음)입니다. 가입자 는 이벤트 객체에서 속성 설정 해야 합니다). 그리고 일단 당신이 그 라인을 시작하면, 당신은 EventHandler<T>일부를 사용할 수도 있습니다 T.


코드가 300,000 개의 라인 프로젝트 내에있을 때보다 간결한 접근 방식의 이점이 있습니다.

이 작업을 사용하면 bool, int 및 Blah가 무엇인지 말해 줄 방법이 없습니다. 조치가 매개 변수를 정의한 오브젝트를 전달한 경우 ok입니다.

EventArgs를 원하는 EventHandler를 사용하고 목적을 주석 처리 한 특성에 대한 getter로 DiagnosticsArgs 예제를 완료하면 더 이해하기 쉽습니다. 또한 DiagnosticsArgs 생성자에서 인수에 주석을 달거나 이름을 지정하십시오.


표준 이벤트 패턴을 따르는 경우 확장 방법을 추가하여 이벤트 발생을보다 안전하고 쉽게 확인할 수 있습니다. 다음 코드는 null 검사를 수행하는 SafeFire ()라는 확장 메서드를 추가하고 이벤트에 영향을 줄 수있는 일반적인 null 경쟁 조건에서 안전하도록 이벤트를 별도의 변수에 복사합니다.

(널 객체에 확장 메서드를 사용 해야하는지 여부는 두 가지입니다.)

public static class EventFirer
{
    public static void SafeFire<TEventArgs>(this EventHandler<TEventArgs> theEvent, object obj, TEventArgs theEventArgs)
        where TEventArgs : EventArgs
    {
        if (theEvent != null)
            theEvent(obj, theEventArgs);
    }
}

class MyEventArgs : EventArgs
{
    // Blah, blah, blah...
}

class UseSafeEventFirer
{
    event EventHandler<MyEventArgs> MyEvent;

    void DemoSafeFire()
    {
        MyEvent.SafeFire(this, new MyEventArgs());
    }

    static void Main(string[] args)
    {
        var x = new UseSafeEventFirer();

        Console.WriteLine("Null:");
        x.DemoSafeFire();

        Console.WriteLine();

        x.MyEvent += delegate { Console.WriteLine("Hello, World!"); };
        Console.WriteLine("Not null:");
        x.DemoSafeFire();
    }
}

보면 표준 .NET 이벤트 패턴 우리가 발견

The standard signature for a .NET event delegate is:

void OnEventRaised(object sender, EventArgs args);

[...]

The argument list contains two arguments: the sender, and the event arguments. The compile time type of sender is System.Object, even though you likely know a more derived type that would always be correct. By convention, use object.

Below on same page we find an example of the typical event definition which is something like

public event EventHandler<EventArgs> EventName;

Had we defined

class MyClass
{
  public event Action<MyClass, EventArgs> EventName;
}

the handler could have been

void OnEventRaised(MyClass sender, EventArgs args);

where sender has the correct (more derived) type.

참고URL : https://stackoverflow.com/questions/1431359/event-action-vs-event-eventhandler

반응형