수색…


소개

이벤트 란 마우스 클릭과 같은 어떤 일이 발생했거나 경우에 따라 가격 변경과 같은 일이 발생한다는 알림입니다.

클래스는 이벤트를 정의 할 수 있으며 인스턴스 (객체)가 이러한 이벤트를 발생시킬 수 있습니다. 예를 들어, 버튼에는 사용자가 클릭했을 때 발생하는 Click 이벤트가 포함될 수 있습니다.

이벤트 핸들러는 해당 이벤트가 발생할 때 호출되는 메소드입니다. 폼에는 포함 된 모든 Button에 대한 Clicked 이벤트 핸들러가 포함될 수 있습니다.

매개 변수

매개 변수 세부
EventArgsT EventArgs에서 파생되고 이벤트 매개 변수를 포함하는 형식입니다.
EventName 이벤트 이름.
처리기 이름 이벤트 처리기의 이름입니다.
SenderObject 이벤트를 호출하는 객체입니다.
EventArguments 이벤트 매개 변수를 포함하는 EventArgsT 유형의 인스턴스입니다.

비고

이벤트를 제기 할 때 :

  • 대리자가 null 인지 항상 확인하십시오. null 위임은 이벤트에 구독자가 없음을 의미합니다. 구독자가없는 이벤트를 발생 NullReferenceException 합니다.
6.0
  • null을 확인하거나 이벤트를 발생시키기 전에 대리자 (예 : EventName )를 로컬 변수 (예 : eventName )에 복사합니다. 이렇게하면 멀티 스레드 환경에서 경쟁 조건을 피할 수 있습니다.

틀린 :

    if(Changed != null)      // Changed has 1 subscriber at this point
                             // In another thread, that one subscriber decided to unsubscribe
        Changed(this, args); // `Changed` is now null, `NullReferenceException` is thrown.

오른쪽 :

    // Cache the "Changed" event as a local. If it is not null, then use
    // the LOCAL variable (handler) to raise the event, NOT the event itself.
    var handler = Changed;
    if(handler != null)
        handler(this, args);
6.0
  • if 문에서 구독자에 대한 대리자를 null 확인하는 대신 메서드를 발생시키는 데 null 조건부 연산자 (?)를 사용합니다. EventName?.Invoke(SenderObject, new EventArgsT());
  • Action <>을 사용하여 대리자 형식을 선언하는 경우 익명 메서드 / 이벤트 처리기 서명은 이벤트 선언의 선언 된 익명 대리자 형식과 동일해야합니다.

이벤트 선언 및 발생

이벤트 선언

다음 구문을 사용하여 모든 class 또는 struct 에서 이벤트를 선언 할 수 있습니다.

public class MyClass
{
    // Declares the event for MyClass
    public event EventHandler MyEvent;

    // Raises the MyEvent event
    public void RaiseEvent()
    {
        OnMyEvent();
    }
}    

이벤트를 선언하기위한 확장 구문은 이벤트의 전용 인스턴스를 보유하고 addset 접근자를 사용하여 공용 인스턴스를 정의합니다. 구문은 C # 속성과 매우 유사합니다. 컴파일러는 여러 스레드가 클래스의 이벤트에 이벤트 처리기를 안전하게 추가하고 제거 할 수 있도록 코드를 생성하기 때문에 위에 설명 된 구문을 사용하는 것이 좋습니다.

이벤트 모금

6.0
private void OnMyEvent()
{
    EventName?.Invoke(this, EventArgs.Empty); 
}
6.0
private void OnMyEvent()
{
    // Use a local for EventName, because another thread can modify the
    // public EventName between when we check it for null, and when we
    // raise the event.
    var eventName = EventName;

    // If eventName == null, then it means there are no event-subscribers,
    // and therefore, we cannot raise the event.
    if(eventName != null)
        eventName(this, EventArgs.Empty);

}

이벤트는 선언 유형에 의해서만 제기 될 수 있습니다. 클라이언트는 가입 / 탈퇴 만 할 수 있습니다.

6.0 이전의 C # 버전에서 EventName?.Invoke 가 지원되지 않는 경우 예제와 같이 호출 전에 임시 변수에 이벤트를 할당하면 여러 스레드가 동일한 스레드를 실행하는 경우 스레드 안전성을 보장 할 수 있습니다. 암호. 이렇게하지 않으면 여러 스레드가 동일한 객체 인스턴스를 사용하는 경우에 NullReferenceException 이 발생합니다. C # 6.0에서 컴파일러는 C # 6의 코드 예제와 비슷한 코드를 내 보냅니다.

표준 이벤트 선언

이벤트 선언 :

public event EventHandler<EventArgsT> EventName;

이벤트 처리기 선언 :

public void HandlerName(object sender, EventArgsT args) { /* Handler logic */ }

이벤트 구독 :

동적으로 :

EventName += HandlerName;

디자이너를 통해 :

  1. 컨트롤의 속성 창에서 이벤트 버튼을 클릭합니다 (Lightening bolt).
  2. 이벤트 이름을 두 번 클릭하십시오.

여기에 이미지 설명을 입력하십시오.

  1. Visual Studio에서 이벤트 코드를 생성합니다.
private void Form1_Load(object sender, EventArgs e)
{

}

메소드 호출 :

EventName(SenderObject, EventArguments);

익명 이벤트 처리기 선언

이벤트 선언 :

public event EventHandler<EventArgsType> EventName;

람다 연산자 => 를 사용하고 이벤트에 가입하는 이벤트 핸들러 선언 :

EventName += (obj, eventArgs) => { /* Handler logic */ };

대리자 익명 메서드 구문을 사용하는 이벤트 처리기 선언 :

EventName += delegate(object obj, EventArgsType eventArgs) { /* Handler Logic */ };

이벤트의 매개 변수를 사용하지 않는 이벤트 핸들러의 선언 및 가입이므로 매개 변수를 지정하지 않아도 위의 구문을 사용할 수 있습니다.

EventName += delegate { /* Handler Logic */ }

이벤트 호출 :

EventName?.Invoke(SenderObject, EventArguments);

비표준 이벤트 선언

이벤트는 EventHandlerEventHandler<T> 뿐만 아니라 모든 대리자 유형이 될 수 있습니다. 예 :

//Declaring an event
public event Action<Param1Type, Param2Type, ...> EventName;

표준 EventHandler 이벤트와 유사하게 사용됩니다.

//Adding a named event handler
public void HandlerName(Param1Type parameter1, Param2Type parameter2, ...) {
    /* Handler logic */
}
EventName += HandlerName;

//Adding an anonymous event handler
EventName += (parameter1, parameter2, ...) => { /* Handler Logic */ };

//Invoking the event
EventName(parameter1, parameter2, ...);

필드와 지역 변수와 비슷하게 단일 명령문에 같은 유형의 여러 이벤트를 선언 할 수 있습니다 (그러나 이것은 종종 나쁜 생각 일 수 있음).

public event EventHandler Event1, Event2, Event3;

이것은 EventHandler 유형의 세 가지 개별 이벤트 ( Event1 , Event2Event3 )를 선언합니다.
참고 : 일부 컴파일러는 클래스뿐만 아니라 인터페이스에서도이 구문을 사용할 수 있지만 C # 사양 (v5.0 §13.2.3)에서는 허용하지 않는 인터페이스에 대한 문법을 ​​제공하므로 인터페이스에서 사용하면 다른 컴파일러에서 신뢰할 수 없게 될 수 있습니다.

추가 데이터가 포함 된 사용자 지정 EventArg 만들기

사용자 정의 이벤트는 대개 이벤트에 대한 정보를 포함하는 사용자 정의 이벤트 인수가 필요합니다. MouseDown 또는 MouseUp 이벤트와 같은 마우스 이벤트에 사용되는 MouseEventArgs 에는 이벤트를 생성하는 데 사용 된 Location 또는 Buttons 에 대한 정보가 들어 있습니다.

새 이벤트를 만들 때 맞춤 이벤트 arg를 만들려면 :

  • EventArgs 에서 파생되는 클래스를 만들고 필요한 데이터에 대한 속성을 정의합니다.
  • 규약에 따라 클래스 이름은 EventArgs 끝나야합니다.

아래 예제에서는 클래스의 Price 속성에 대한 PriceChangingEventArgs 이벤트를 만듭니다. 이벤트 데이터 클래스에는 CurrentPriceNewPrice 됩니다. 이 이벤트는 Price 속성에 새 값을 할당하고 소비자가 값이 변경되고 있음을 알리고 현재 가격과 새 가격을 알 수있게하면 발생합니다.

PriceChangingEventArgs

public class PriceChangingEventArgs : EventArgs
{
    public PriceChangingEventArgs(int currentPrice, int newPrice)
    {
        this.CurrentPrice = currentPrice;
        this.NewPrice = newPrice;
    }

    public int CurrentPrice { get; private set; }
    public int NewPrice { get; private set; }
}

생성물

public class Product
{
    public event EventHandler<PriceChangingEventArgs> PriceChanging;

    int price;
    public int Price
    {
        get { return price; }
        set
        {
            var e = new PriceChangingEventArgs(price, value);
            OnPriceChanging(e);
            price = value;
        }
    }

    protected void OnPriceChanging(PriceChangingEventArgs e)
    {
        var handler = PriceChanging;
        if (handler != null)
            handler(this, e);
    }
}

소비자가 새 값을 변경하도록 허용 한 다음 값을 속성에 사용하여 예제를 향상시킬 수 있습니다. 이렇게하면 수업에서 이러한 변경 사항을 적용하는 것으로 충분합니다.

설정 가능한 NewPrice 의 정의를 변경하십시오.

public int NewPrice { get; set; }

e.NewPrice 을 호출 한 후 OnPriceChanging 를 속성의 값으로 사용하도록 Price 의 정의를 변경합니다.

int price;
public int Price
{
    get { return price; }
    set
    {
        var e = new PriceChangingEventArgs(price, value);
        OnPriceChanging(e);
        price = e.NewPrice;
    }
}

취소 가능한 이벤트 만들기

그 예로서, 해제 할 수있는 동작을 수행하고있을 때 취소 가능한 이벤트 클래스에 의해 상승 될 수 FormClosing (A)의 이벤트 Form .

이러한 이벤트를 생성하려면 다음을 수행하십시오.

  • CancelEventArgs 에서 파생 된 새 이벤트 arg를 작성하고 이벤트 데이터에 대한 추가 특성을 추가하십시오.
  • EventHandler<T> 를 사용하여 이벤트를 만들고 생성 한 새 cancel 이벤트 arg 클래스를 사용하십시오.

아래 예제에서는 클래스의 Price 속성에 대한 PriceChangingEventArgs 이벤트를 만듭니다. 이벤트 데이터 클래스에는 소비자가 새 정보를 알 수 있도록하는 Value 가 들어 있습니다. 이 이벤트는 Price 속성에 새 값을 할당하고 소비자가 값이 변경되고 있음을 알리고 이벤트를 취소하도록 할 때 발생합니다. 소비자가 이벤트를 취소하면 이전 Price 값이 사용됩니다.

PriceChangingEventArgs

public class PriceChangingEventArgs : CancelEventArgs
{
    int value;
    public int Value
    {
        get { return value; }
    }
    public PriceChangingEventArgs(int value)
    {
        this.value = value;
    }
}

생성물

public class Product
{
    int price;
    public int Price
    {
        get { return price; }
        set
        {
            var e = new PriceChangingEventArgs(value);
            OnPriceChanging(e);
            if (!e.Cancel)
                price = value;
        }
    }

    public event EventHandler<PriceChangingEventArgs> PropertyChanging;
    protected void OnPriceChanging(PriceChangingEventArgs e)
    {
        var handler = PropertyChanging;
        if (handler != null)
            PropertyChanging(this, e);
    }
}

이벤트 속성

클래스에서 이벤트 수가 많아지면 대리인 당 한 필드의 저장 비용이 용납되지 않을 수 있습니다. .NET Framework는 이러한 경우에 대한 이벤트 속성 을 제공합니다. 이렇게하면 EventHandlerList 와 같은 다른 데이터 구조를 사용하여 이벤트 대리자를 저장할 수 있습니다.

public class SampleClass 
{
    // Define the delegate collection.
    protected EventHandlerList eventDelegates = new EventHandlerList();

    // Define a unique key for each event.
    static readonly object someEventKey = new object();

    // Define the SomeEvent event property.
    public event EventHandler SomeEvent
    {
        add
        {
            // Add the input delegate to the collection.
            eventDelegates.AddHandler(someEventKey, value);
        }
        remove
        {
            // Remove the input delegate from the collection.
            eventDelegates.RemoveHandler(someEventKey, value);
        }
    }

    // Raise the event with the delegate specified by someEventKey
    protected void OnSomeEvent(EventArgs e)
    {
        var handler = (EventHandler)eventDelegates[someEventKey];
        if (handler != null)
            handler(this, e);
    }
}

이 접근법은 WinForms와 같은 GUI 프레임 워크에서 널리 사용됩니다. 여기에는 컨트롤에 수십 개 심지어 수백 개의 이벤트가있을 수 있습니다.

EventHandlerList 는 스레드로부터 안전하지 않으므로 클래스가 여러 스레드에서 사용될 것으로 예상되는 경우 잠금 문이나 기타 동기화 메커니즘을 추가하거나 스레드 안전성을 제공하는 저장소를 사용해야합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow