Program Club

C # 델리게이트가 필요한 이유

proclub 2020. 12. 29. 07:30
반응형

C # 델리게이트가 필요한 이유


왜 우리에게 대표자가 필요한지 이해하지 못하는 것 같습니까? 메서드 참조를 보유하는 불변 참조 형식이라는 것을 알고 있지만 대리자를 통해 호출하는 대신 메서드를 직접 호출 할 수없는 이유는 무엇입니까?

감사


물론 개체에서 직접 메서드를 호출 할 수 있지만 다음 시나리오를 고려하십시오.

  1. 메서드 호출을 많이 작성하지 않고 단일 대리자를 사용하여 일련의 메서드를 호출하려고합니다.
  2. 이벤트 기반 시스템을 우아하게 구현하고 싶습니다.
  3. 서명에서 동일한 두 메서드를 호출하지만 다른 클래스에 상주하려고합니다.
  4. 메소드를 매개 변수로 전달하려고합니다.
  5. LINQ 에서처럼 많은 다형성 코드를 작성하고 싶지는 않습니다 Select. 메서드에 많은 구현을 제공 할 수 있습니다 .

간단한 대답 : 작업을 수행해야하는 코드는 작성 될 때 호출 할 메서드를 알지 못합니다. 컴파일 타임에 어떤 메서드를 호출해야하는지 아는 경우에만 메서드를 직접 호출 할 수 있습니다. 따라서 "적절한 시간에 X 작업 수행"이라는 개념을 추상화하려면 작업을 호출하는 메서드가 미리 정확한 구현을 알 필요가 없도록 작업에 대한 표현이 필요합니다.

예를 들면 :

  • Enumerable.Select LINQ에서 말하지 않으면 사용할 프로젝션을 알 수 없습니다.
  • 의 저자는 Button무엇을 몰랐다 사용자가 클릭 할 때 작업이되고 싶어
  • 새 스레드가 한 가지만 수행했다면 꽤 지루할 것입니다 ...

델리게이트를 단일 메서드 인터페이스처럼 생각하는 데 도움이 될 수 있지만 사용하기 쉽게 만드는 많은 언어 구문과 비동기 실행 및 멀티 캐스팅에 대한 펑키 지원이 있습니다.


당신은하지 않을 수 있기 때문에 방법은 아직 작성, 또는 당신이 그것의 사용자가 사용자가 클래스가 실행하고자하는 어떤 방법 (사용자가 쓴)를 결정할 수있는 그런 방식으로 수업을 설계했다.

또한 특정 디자인을 더 깔끔하게 만들고 (예를 들어, 다른 메서드를 호출하는 switch 문 대신 전달 된 델리게이트를 호출합니다) 이해하기 쉽고 코드를 변경하지 않고도 코드를 확장 할 수 있습니다 (OCP를 생각해보세요).

델리게이트는 이벤트 시스템의 기반이기도합니다. 델리게이트없이 이벤트 핸들러를 작성하고 등록하는 것은 그들과 함께하는 것보다 훨씬 어려울 것입니다.

Linq에서 다른 대표자 ActionFunc대표자를 확인하십시오 -그들 없이는 거의 유용하지 않을 것입니다.

그렇긴해도 누구도 델리게이트를 사용하도록 강요하지 않습니다.


  1. 델리게이트는 이벤트를 지원합니다.
  2. 델리게이트는 컴파일 타임에 메서드가 무엇인지 정확히 알 필요없이 프로그램에 메서드를 실행할 수있는 방법을 제공합니다.

델리게이트로 할 수있는 모든 것은 그들 없이도 할 수 있습니다.하지만 대리자는 훨씬 더 깔끔한 방법을 제공합니다. 델리게이트가 없다면 Invoke (적절한 매개 변수) 함수를 포함하는 모든 가능한 함수 시그니처에 대해 인터페이스 또는 추상 기본 클래스를 정의하고 의사 델리게이트가 호출 할 수있는 각 함수에 대한 클래스를 정의해야합니다. 그 클래스는 함수의 시그니처에 대한 적절한 인터페이스를 상속하고, 표현해야 할 함수를 포함하는 클래스에 대한 참조를 포함하며, 보유하고있는 클래스에서 적절한 함수를 호출하는 Invoke (적절한 매개 변수)를 구현하는 메소드를 포함합니다. 참조. 클래스 Foo에 두 개의 메서드 Foo1 및 Foo2가 있고 둘 다 단일 매개 변수를 사용하며 둘 다 의사 위임자가 호출 할 수있는 경우 각 메서드에 대해 하나씩 두 개의 추가 클래스가 생성됩니다.

이 기술에 대한 컴파일러 지원이 없다면 소스 코드는 매우 끔찍할 것입니다. 그러나 컴파일러가 적절한 중첩 클래스를 자동 생성 할 수 있다면 상황이 매우 깨끗할 수 있습니다. 의사 델리게이트에 대한 디스패치 속도는 일반적으로 기존 델리게이트보다 느릴 수 있지만 의사 델리게이트가 추상 기본 클래스가 아닌 인터페이스 인 경우 지정된 서명의 한 메서드에 대해 의사 델리게이트를 만들기 만하면되는 클래스는 적절한 의사-대리자 인터페이스 자체를 구현합니다. 그런 다음 클래스 인스턴스를 해당 서명의 의사 위임을 예상하는 모든 코드에 전달할 수 있으므로 추가 개체를 만들 필요가 없습니다. 또한 의사 대리자를 사용할 때 필요한 클래스의 수가 "실제"대리자를 사용할 때보 다 많지만,


C / C ++ 함수 포인터와 자바 스크립트 이벤트 처리 함수를 "데이터"로 취급하고 전달하는 방법을 생각해보십시오. Delphi 언어에는 절차 유형도 있습니다. 이면에서 C # 델리게이트 및 람다 식, 그리고 모든 것들은 본질적으로 동일한 아이디어입니다. 그리고 이것은 함수형 프로그래밍의 기초를 구성합니다.


함수를 매개 변수로 전달하는 이유에 대한 예를 물었고, 완벽한 기능을 가지고 있으며 이해하는 데 도움이 될 것이라고 생각했습니다. 꽤 학문적이지만 사용을 보여줍니다. ListResults () 메서드와 getFromCache () 메서드가 있다고 가정합니다. 오히려 캐시가 null인지 등 많은 검사를 수행합니다. getCache에 모든 메소드를 전달한 다음 getFromCache 메소드 내에서 캐시가 비어있는 경우에만 호출 할 수 있습니다.

_cacher.GetFromCache(delegate { return ListResults(); }, "ListResults");

public IEnumerable<T> GetFromCache(MethodForCache item, string key, int minutesToCache = 5)
    {
        var cache = _cacheProvider.GetCachedItem(key);
        //you could even have a UseCache bool here for central control
        if (cache == null)
        {
            //you could put timings, logging etc. here instead of all over your code
            cache = item.Invoke();
            _cacheProvider.AddCachedItem(cache, key, minutesToCache);
        }            

        return cache;
    }

C / C ++의 함수에 대한 포인터와 유사한 구조로 생각할 수 있습니다. 그러나 그들은 C #에서 그 이상입니다. 세부 사항 .

참조 URL : https://stackoverflow.com/questions/4284493/why-do-we-need-c-sharp-delegates

반응형