.NET 플랫폼을 접하는 개발자는 delegates
기반으로 하는 디자인과 events
기반의 디자인 중에서 결정할 때 종종 어려움을 겪습니다. 두 언어 기능이 유사하기 때문에 대리자 또는 이벤트를 선택하는 것이 어려운 경우가 많습니다. 이벤트는 대리자 언어 지원을 사용하여 빌드됩니다. 이벤트 처리기 선언은 대리자 형식을 선언합니다.
둘 다 구성 요소가 런타임에만 알려진 메서드를 호출하여 통신하는, 지연 바인딩 시나리오를 제공합니다. 둘 다 단일 및 여러 구독자 메서드를 지원합니다. 이러한 용어를 단일 캐스트 및 멀티캐스트 지원이라고 할 수 있습니다. 둘 다 처리기를 추가하고 제거하기 위한 유사한 구문을 지원합니다. 마지막으로 이벤트를 발생시키고 대리자를 호출하는 경우 정확히 동일한 메서드 호출 구문을 사용합니다. 둘 다 Invoke()
연산자에 사용하기 위해 동일한 ?.
메서드 구문을 지원합니다.
이러한 모든 유사성을 사용하면 사용할 시기를 결정하는 데 쉽게 어려움을 겪을 수 있습니다.
이벤트 듣기는 선택 사항입니다.
사용할 언어 기능을 결정할 때 가장 중요한 고려 사항은 연결된 구독자가 있어야 하는지 여부입니다. 코드가 구독자가 제공한 코드를 호출해야 하는 경우 콜백을 구현해야 할 때 대리자를 기반으로 하는 디자인을 사용해야 합니다. 코드가 구독자를 호출하지 않고 모든 작업을 완료할 수 있는 경우 이벤트를 기반으로 디자인을 사용해야 합니다.
이 섹션에서 빌드한 예제를 고려해 보세요. 요소를 올바르게 정렬하려면 List.Sort()
사용하여 빌드한 코드에 비교자 함수가 지정되어야 합니다. 반환할 요소를 결정하려면 LINQ 쿼리에 대리자를 제공해야 합니다. 둘 다 대리자를 사용하여 빌드된 디자인을 사용했습니다.
Progress
이벤트를 고려합니다. 작업에 대한 진행률을 보고합니다. 수신기가 있는지 여부에 관계없이 작업은 계속 진행됩니다.
FileSearcher
또 다른 예입니다. 이벤트 구독자가 연결되어 있지 않더라도 검색된 모든 파일을 검색하고 찾을 수 있습니다. 이벤트를 수신 대기하는 구독자가 없는 경우에도 UX 컨트롤은 여전히 올바르게 작동합니다. 둘 다 이벤트를 기반으로 디자인을 사용합니다.
반환 값에는 대리자가 필요합니다.
또 다른 고려 사항은 대리자 메서드에 원하는 메서드 프로토타입입니다. 보신 것처럼, 이벤트에 사용되는 대리자는 모두 반환 형식이 void입니다. 이벤트 인수 개체의 속성을 수정하여 정보를 이벤트 원본으로 다시 전달하는 이벤트 처리기를 만드는 관용구가 있습니다. 이러한 관용구는 작동하지만 메서드에서 값을 반환하는 것만큼 자연적이지는 않습니다.
대리자 메서드가 값을 반환하면 알고리즘에 어떤 식으로든 영향을 주는 두 가지 추론이 있을 수 있습니다.
이벤트에는 비공개 호출이 있습니다.
이벤트가 포함된 클래스 이외의 클래스는 이벤트 수신기만 추가 및 제거할 수 있습니다. 이벤트를 포함하는 클래스만 이벤트를 호출할 수 있습니다. 이벤트는 일반적으로 퍼블릭 클래스 멤버입니다. 이에 비해 대리자는 매개 변수로 전달되고 프라이빗 클래스 멤버로 저장되는 경우가 많습니다.
이벤트 수신기의 수명이 더 긴 경우가 많습니다.
이벤트 리스너의 수명이 길어지는 것은 약간 설득력이 떨어지는 정당화입니다. 그러나 이벤트 원본이 오랜 기간 동안 이벤트를 발생시키는 경우 이벤트 기반 디자인이 더 자연스러워질 수 있습니다. 많은 시스템에서 UX 컨트롤에 대한 이벤트 기반 디자인의 예를 볼 수 있습니다. 프로그램의 수명 동안 이벤트를 발생할 수 있는 이벤트 소스를 구독하면 됩니다. (더 이상 필요하지 않은 경우 이벤트에서 구독을 취소할 수 있습니다.)
대리자가 메서드에 대한 인수로 사용되고 해당 메서드가 반환된 후에는 대리자가 사용되지 않는 대리자 기반 디자인이 많은 것과 대조됩니다.
신중하게 평가
위의 고려 사항은 어렵고 빠른 규칙이 아닙니다. 대신 특정 사용에 가장 적합한 선택을 결정하는 데 도움이 되는 지침을 나타냅니다. 유사하기 때문에 둘 다 프로토타입을 만들 수 있으며 작업하는 것이 더 자연스러운 것을 고려할 수 있습니다. 둘 다 지연 바인딩 시나리오를 잘 처리합니다. 디자인을 가장 잘 전달하는 것을 사용합니다.
.NET