.NET의 이벤트는 대리자 모델을 기반으로 합니다. 대리자 모델은 구독자가 공급자에 등록하고 공급자로부터 알림을 받을 수 있도록 하는 관찰자 디자인 패턴을 따릅니다. 이벤트 발신자는 이벤트가 발생할 때 알림을 푸시합니다. 이벤트 수신기는 응답을 정의합니다. 이 문서에서는 대리자 모델의 주요 구성 요소, 애플리케이션에서 이벤트를 사용하는 방법 및 코드에서 이벤트를 구현하는 방법을 설명합니다.
이벤트 발신자를 사용하여 이벤트를 트리거하십시오
이벤트는 동작 발생을 알리기 위해 개체에서 보낸 메시지입니다. 이 작업은 단추 누르기 등의 사용자 상호 작용이거나 속성 값 변경과 같은 다른 프로그램 논리에서 발생할 수 있습니다. 이벤트를 발생시키는 개체를 이벤트 발신자라고 합니다. 이벤트 발신자는 이벤트 발생 이벤트를 수신(처리)하는 개체 또는 메서드를 모릅니다. 이벤트는 보통 이벤트 송신자의 구성원입니다. 예를 들어 Click 이벤트는 클래스의 Button 멤버이며 PropertyChanged , 이벤트는 인터페이스를 구현 INotifyPropertyChanged 하는 클래스의 멤버입니다.
이벤트를 정의하려면 이벤트 클래스의 서명에 C# 이벤트 또는 Visual Basic Event 키워드를 사용하고 이벤트에 대한 대리자 유형을 지정합니다. 대리자는 다음 섹션에서 설명합니다.
일반적으로, 이벤트를 발생시키려면 C#에서는 protected
과 virtual
으로, Visual Basic에서는 Protected
과 Overridable
로 표시된 메서드를 추가합니다. 메서드 On<EventName>
의 명명 규칙은 다음과 같습니다 OnDataReceived
. 메서드는 형식 또는 파생 형식 EventArgs 의 개체인 이벤트 데이터 개체를 지정하는 하나의 매개 변수를 사용해야 합니다. 파생 클래스가 이벤트를 발생시키는 논리를 재정의할 수 있도록 이 메서드를 제공합니다. 파생 클래스는 항상 기본 클래스의 메서드를 호출 On<EventName>
하여 등록된 대리자가 이벤트를 수신하도록 해야 합니다.
다음 예제에서는 이름이 지정된 ThresholdReached
이벤트를 선언하는 방법을 보여 있습니다. 이벤트는 EventHandler 대리자와 연결되어 OnThresholdReached
라는 메서드에서 발생합니다.
class Counter
{
public event EventHandler ThresholdReached;
protected virtual void OnThresholdReached(EventArgs e)
{
ThresholdReached?.Invoke(this, e);
}
// provide remaining implementation for the class
}
Public Class Counter
Public Event ThresholdReached As EventHandler
Protected Overridable Sub OnThresholdReached(e As EventArgs)
RaiseEvent ThresholdReached(Me, e)
End Sub
' provide remaining implementation for the class
End Class
이벤트 처리기에 대한 대리자 서명 선언
대리자는 메서드에 대한 참조를 보유하는 형식입니다. 대리자는 참조하는 메서드에 대한 반환 형식 및 매개 변수를 보여 주는 서명으로 선언됩니다. 서명과 일치하는 메서드에 대한 참조만 보유할 수 있습니다. 대리자는 형식이 안전한 함수 포인터 또는 콜백과 동일합니다. 대리자 선언은 대리자 클래스를 정의하기에 충분합니다.
대리자는 .NET에서 많은 용도를 사용합니다. 이벤트의 컨텍스트에서 대리자는 이벤트 소스와 이벤트를 처리하는 코드 사이의 중간(또는 포인터와 유사한 메커니즘)입니다. 이전 섹션의 예제와 같이 이벤트 선언에 대리자 형식을 포함하여 대리자를 이벤트와 연결합니다. 대리자에 대한 자세한 내용은 클래스를 참조하세요 Delegate .
.NET은 대부분의 이벤트 시나리오를 지원하기 위해 EventHandler 및 EventHandler<TEventArgs> 대리자를 제공합니다. EventHandler 이벤트 데이터를 포함하지 않는 모든 이벤트에 대리자를 사용합니다. EventHandler<TEventArgs> 이벤트에 대한 데이터를 포함하는 이벤트에 대리자를 사용합니다. 이러한 대리자는 반환 형식 값이 없으며 두 개의 매개 변수(이벤트 원본의 개체 및 이벤트 데이터의 개체)를 사용합니다.
대리자는 멀티캐스트 클래스 개체입니다. 즉, 둘 이상의 이벤트 처리 메서드에 대한 참조를 보유할 수 있습니다. 자세한 내용은 참조 페이지를 참조 Delegate 하세요. 대리자는 이벤트 처리에서 유연성과 세분화된 제어를 제공합니다. 대리자는 이벤트에 대해 등록된 이벤트 처리기 목록을 유지 관리하여 이벤트를 발생시키는 클래스에 대한 이벤트 디스패처 역할을 합니다.
EventHandler 및 EventHandler<TEventArgs> 대리자 타입을 사용하여 필요한 대리자를 정의합니다. 선언에서 C#의 delegate
형식 또는 Visual Basic의 Delegate
형식으로 대리자를 표시합니다. 다음 예제에서는 명명 ThresholdReachedEventHandler
된 대리자를 선언하는 방법을 보여줍니다.
public delegate void ThresholdReachedEventHandler(object sender, ThresholdReachedEventArgs e);
Public Delegate Sub ThresholdReachedEventHandler(sender As Object, e As ThresholdReachedEventArgs)
이벤트 데이터 클래스 작업
이벤트와 연결된 데이터는 이벤트 데이터 클래스를 통해 제공할 수 있습니다. .NET은 애플리케이션에서 사용할 수 있는 많은 이벤트 데이터 클래스를 제공합니다. 예를 들어, SerialDataReceivedEventArgs 클래스는 SerialPort.DataReceived 이벤트의 이벤트 데이터 클래스입니다. .NET은 모든 이벤트 데이터 클래스가 접미사로 EventArgs
끝나는 명명 패턴을 따릅니다. 이벤트에 대한 대리자를 확인하여 이벤트와 연결된 이벤트 데이터 클래스를 결정합니다. 예를 들어 대리자는 SerialDataReceivedEventHandler 클래스를 SerialDataReceivedEventArgs 매개 변수로 포함합니다.
EventArgs 이 클래스는 일반적으로 이벤트 데이터 클래스의 기본 형식입니다. 이벤트에 연결된 데이터가 없는 경우에도 이 클래스를 사용합니다. 구독자에게 추가 데이터 없이 발생한 일을 알리는 이벤트를 만들 때 클래스를 대리자의 EventArgs 두 번째 매개 변수로 포함합니다. 데이터가 제공되지 않으면 EventArgs.Empty 값을 전달할 수 있습니다. 대리자는 EventHandler 클래스를 EventArgs 매개 변수로 포함합니다.
EventArgs 클래스에서 파생되는 클래스를 생성하여 이벤트 관련 데이터를 전달하는 데 필요한 멤버를 제공할 수 있습니다. 일반적으로 .NET과 동일한 명명 패턴을 사용하고 접미사로 EventArgs
이벤트 데이터 클래스 이름을 종료해야 합니다.
다음 예제에서는 발생 중인 이벤트와 관련된 속성을 포함하는 명명 ThresholdReachedEventArgs
된 이벤트 데이터 클래스를 보여 줍니다.
public class ThresholdReachedEventArgs : EventArgs
{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}
Public Class ThresholdReachedEventArgs
Inherits EventArgs
Public Property Threshold As Integer
Public Property TimeReached As DateTime
End Class
처리기를 사용하여 이벤트에 응답
이벤트에 응답하려면 이벤트 수신기에서 이벤트 처리기 메서드를 정의합니다. 이 메서드는 처리 중인 이벤트에 대한 대리자의 서명과 일치해야 합니다. 이벤트 처리기에서 사용자가 단추를 누른 후 사용자 입력을 수집하는 등 이벤트가 발생할 때 필요한 작업을 수행합니다. 이벤트가 발생할 때 알림을 받으려면 이벤트 처리기 메서드가 이벤트를 구독해야 합니다.
다음 예제는 c_ThresholdReached
라는 이벤트 처리기 메서드를 보여주며, 이는 EventHandler 대리자의 서명과 일치합니다. 메서드는 이벤트를 구독합니다.ThresholdReached
class ProgramTwo
{
static void Main()
{
var c = new Counter();
c.ThresholdReached += c_ThresholdReached;
// provide remaining implementation for the class
}
static void c_ThresholdReached(object sender, EventArgs e)
{
Console.WriteLine("The threshold was reached.");
}
}
Module Module1
Sub Main()
Dim c As New Counter()
AddHandler c.ThresholdReached, AddressOf c_ThresholdReached
' provide remaining implementation for the class
End Sub
Sub c_ThresholdReached(sender As Object, e As EventArgs)
Console.WriteLine("The threshold was reached.")
End Sub
End Module
정적 및 동적 이벤트 처리기 사용
.NET을 사용하면 구독자가 이벤트 알림을 정적으로 또는 동적으로 등록할 수 있습니다. 정적 이벤트 처리기는 이벤트가 처리되는 클래스의 전체 수명 동안 적용됩니다. 동적 이벤트 처리기는 일반적으로 일부 조건부 프로그램 논리에 대한 응답으로 프로그램 실행 중에 명시적으로 활성화되고 비활성화됩니다. 이벤트 알림이 특정 조건에서만 필요하거나 런타임 조건에 따라 호출할 특정 처리기가 결정되는 경우 동적 처리기를 사용할 수 있습니다. 이전 섹션의 예제에서는 이벤트 처리기를 동적으로 추가하는 방법을 보여 줍니다. 자세한 내용은 이벤트 (Visual Basic의 경우) 및 이벤트 (C#)를 참조하세요.
여러 이벤트를 발생시키다
클래스가 여러 이벤트를 발생하면 컴파일러는 이벤트 대리자 인스턴스당 하나의 필드를 생성합니다. 이벤트 수가 큰 경우 대리자당 하나의 필드의 스토리지 비용이 허용되지 않을 수 있습니다. 이러한 시나리오에서 .NET은 이벤트 대리자를 저장하기 위해 선택한 다른 데이터 구조와 함께 사용할 수 있는 이벤트 속성을 제공합니다.
이벤트 속성은 이벤트 접근자가 함께 포함된 이벤트 선언으로 구성됩니다. 이벤트 접근자는 스토리지 데이터 구조에서 이벤트 대리자 인스턴스를 추가하거나 제거하기 위해 정의하는 메서드입니다.
비고
각 이벤트 대리자를 호출하기 전에 검색해야 하므로 이벤트 속성은 이벤트 필드보다 느립니다.
절충은 메모리와 속도 사이에 있습니다. 클래스가 자주 발생하지 않는 많은 이벤트를 정의하는 경우 이벤트 속성을 구현해야 합니다. 자세한 내용은 이벤트 속성을 사용하여 여러 이벤트 처리를 참조하세요.
관련 작업 살펴보기
다음 리소스는 이벤트 작업과 관련된 다른 작업 및 개념을 설명합니다.
- 이벤트 발생 및 사용: 이벤트를 발생시키고 사용하는 예제를 찾습니다.
- 이벤트 속성을 사용하여 여러 이벤트 처리: 이벤트 속성을 사용하여 여러 이벤트를 처리하는 방법을 알아봅니다.
- 관찰자 디자인 패턴 살펴보기: 구독자가 공급자에 등록하고 공급자로부터 알림을 받을 수 있도록 하는 디자인 패턴을 검토합니다.
사양 참조 검토
사양 참조 설명서는 이벤트 처리를 지원하는 API에 사용할 수 있습니다.
API 이름 | API 형식 | 참고 문헌 |
---|---|---|
EventHandler | 대리인 | EventHandler |
EventHandler<TEventArgs> | 대리인 | EventHandler<TEventArgs> |
EventArgs | 클래스 | EventArgs |
대리인 | 클래스 | Delegate |
관련 콘텐츠
.NET