델리게이트 란 무엇입니까? [닫은]


152

대리인의 실제 역할이 무엇인지 혼동하고 있습니까?

면접에서이 질문을 여러 번 받았지만 면접관이 내 대답에 만족했다고 생각하지 않습니다.

누구나 실례를 통해 한 문장으로 최고의 정의를 말해 줄 수 있습니까?


21
궁금한 점이 있으면 어떻게 대응할 수 있었습니까?
Anthony Forloney

6
이 질문이 종결되었지만 126 개의 공감대가 있으며 65 명이이 질문을 즐겨 찾기로 표시 한 것이 흥미 롭습니다. 너무 넓어도 여전히 좋은 질문입니다.
Rich

답변:


171

델리게이트를 "함수에 대한 포인터"라고 생각하고 싶습니다. 이것은 C 일로 거슬러 올라가지 만 아이디어는 여전히 유효합니다.

아이디어는 코드를 호출 할 수 있어야하지만 호출 할 코드는 런타임까지 알려지지 않는다는 것입니다. 따라서 해당 목적을 위해 "대리인"을 사용합니다. 대리인은 예를 들어 다른 이벤트를 기반으로 다른 작업을 수행하는 이벤트 처리기 등의 작업에 유용합니다.

여기 당신이 볼 수 C #을위한 참조 :

예를 들어 C #에서 계산을하고 런타임까지 알 수없는 다른 계산 방법을 사용하려고한다고 가정 해 보겠습니다. 따라서 다음과 같은 몇 가지 계산 방법이있을 수 있습니다.

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

다음과 같이 델리게이트 서명을 선언 할 수 있습니다.

public delegate double calcTotalDelegate(double amt);

그런 다음 대리자를 다음과 같은 매개 변수로 사용하는 메서드를 선언 할 수 있습니다.

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

그리고 CalcMyTotal사용하려는 델리게이트 메소드를 전달 하는 메소드를 호출 할 수 있습니다.

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);

19
C의 간단하면서도 효과적인 함수 포인터에 대한 +1
Aiden Bell

3
답변과 관련된 질문입니다. 정상적인 방법으로 함수를 호출하는 것과 어떻게 다른가요? 그것 때문에 런타임에 알려지지 않았습니까?
Naveed

1
@NAVEED-최신 편집을 참조하십시오. 예를 포함 시켰습니다. 실제 메소드 호출까지는 위의 예제 (calcTotal (amt)가 대리자를 호출 함)의 일반 메소드 호출과 다르지 않지만 대리자의 힘은 매개 변수로 사용할 수 있다는 것입니다. 메소드가 다른 동작을 가질 수 있기를 원할 때. 당신이 그것들을 사용할 수있는 다른 많은 것들이 있습니다. 이것은 단순한 예일뿐입니다. 희망이 도움이됩니다.
dcp

런타임에 알려지지 않았으며 자유 함수가 아닌 바인딩 된 함수입니다 Foo. 대리자에 비 정적 메소드 를 할당 this.Foo()하면 함수 포인터처럼 정적 함수가 아닌 호출됩니다 (C에서는 종종 추가 void*매개 변수가 있습니다. this함수 포인터에 전달 )
Pete Kirkham

1
C / C ++에서 함수 포인터로 유사성을 설정하는 빠르고 효과적인 예제의 경우 +1 매우 감사!
G21

19

델리게이트는 단순히 함수 포인터입니다.
델리게이트를 실행할 방법을 지정하기 만하면됩니다. 나중에 코드에서 Invoke를 통해 해당 메소드를 호출 할 수 있습니다.

설명 할 코드 (구문이 꺼져있을 수 있도록 메모리에서 작성)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}

16

여기에서 찍은

Q 델리게이트 란 무엇입니까?
A 개체가 요청을 받으면 개체는 요청 자체를 처리하거나 작업을 수행하기 위해 두 번째 개체에 요청을 전달할 수 있습니다. 객체가 요청을 전달하기로 결정하면 객체가 요청을 처리하는 책임을 두 번째 객체로 전달했다고 말합니다.

또는 쉬운 의사 예제로 무언가가 object1에 요청을 보냅니다. 그런 다음 object1은 요청과 그 자체를 object2 (대리인)에게 전달합니다. object2는 요청을 처리하고 일부 작업을 수행합니다. (참고 : 위의 링크는 좋은 예입니다)


위 링크에 제공된 예는 위임을 올바르게 설명하지 않습니다.
Hardik9850


4

델리게이트는 메소드를 참조 할 수있는 객체입니다. 따라서 델리게이트를 만들 때 메서드에 대한 참조를 보유 할 수있는 객체를 만듭니다. 또한이 참조를 통해 메소드를 호출 할 수 있습니다. 따라서 델리게이트는 자신이 참조하는 메소드를 호출 할 수 있습니다. 델리게이트의 주요 장점은 메소드 호출을 지정할 수 있지만 실제로 호출 된 메소드는 컴파일 타임이 아니라 런타임에 결정된다는 것입니다.

간단한 위임

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://knowpacific.wordpress.com/2012/01/26/delegate/


2

여기에서는 델리게이트, 멀티 캐스트 델리게이트 및 사용법을 설명하겠습니다. 델리게이트는 객체에서 메서드 참조를 보유하는 유형입니다. 타입 안전 함수 포인터라고도합니다. 델리게이트는 메소드 서명을 정의하는 유형이라고 말할 수 있습니다.

델리게이트를 인스턴스화 할 때 인스턴스와 호환되는 서명이있는 메소드를 연결할 수 있습니다. 델리게이트 인스턴스를 통해 메소드를 호출하거나 호출 할 수 있습니다. 대리인은 메서드를 다른 메서드에 인수로 전달하는 데 사용됩니다. 이벤트 핸들러는 델리게이트를 통해 호출되는 메소드에 지나지 않습니다. 델리게이트 사용의 장점은 호출자의 메소드 호출 캡슐화 델리게이트를 효과적으로 사용하면 응용 프로그램의 성능이 향상됩니다. 메소드를 비동기 적으로 호출하는 데 사용됩니다. 대리인의 일부 속성이 있습니다

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

공개 대리자 type_of_delegate delegate_name () // 선언

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

다음 예제는 델리게이트 작업을 보여줍니다.

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

멀티 캐스트 델리게이트 란 무엇입니까?

둘 이상의 메소드에 대한 참조를 보유하는 대리자입니다. 멀티 캐스트 대리자는 void를 반환하는 메서드 만 포함해야합니다. 그렇지 않으면 런타임 예외가 있습니다.

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

여기서 위임은 + = 연산자를 사용하여 추가되고-= 연산자를 사용하여 제거됩니다.

델리게이트 유형은 .NET Framework의 델리게이트 클래스에서 파생됩니다. 델리게이트 유형은 봉인되어 있으며 파생 될 수 없습니다. 인스턴스화 된 대리자는 개체이므로 매개 변수로 전달되거나 속성에 할당 될 수 있습니다. 이렇게하면 메서드가 대리자를 매개 변수로 수락하고 나중에 대리자를 호출 할 수 있습니다. 이것을 비동기 콜백이라고합니다.


1

델리게이트 패턴에 대한 자세한 설명과 실제 구현은 Google 컬렉션 전달 클래스 (데코레이터 패턴)에서 확인할 수 있습니다.


1

이벤트 통신 발신자는 이벤트를 처리 할 개체를 모릅니다. 델리게이트는 메소드의 참조를 보유하는 유형입니다. Delegate는 서명을 가지고 있으며 서명과 일치하는 메소드에 대한 참조를 보유하므로 Delegate는 유형 안전 함수 포인터와 같습니다.

button1.Click + = new System.EventHandler (button1_Click) System.EventHandler는 여기에서 대리자로 선언됩니다.

런타임에 호출 할 코드를 모르는 경우 Delegate가 사용되므로 이벤트를 처리하는 데 Delegate가 사용됩니다.

http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx


1

위임 객체는 뭔가 해당 개체에서 발생하면 다른 객체가 협의하는 것이 목적이다. 예를 들어, 자동차에 문제가 발생하면 수리 담당자가 대리인입니다. 당신은 당신의 수리공에게 가서 당신을 위해 차를 수리 해달라고 요청합니다 (어떤 사람들은 자동차를 직접 수리하는 것을 선호하지만,이 경우에는 그들 자신의 자동차 대표입니다).


1

델리게이트는 함수에 대한 포인터를 나타내는 객체입니다. 그러나 다음과 같은 점에서 일반적인 함수 포인터는 아닙니다.

1) 객체 지향

2) 형식이 안전합니다. 즉, 메서드 만 가리킬 수 있고 가리키는 원시 메모리 주소를 읽을 수 없습니다

3) 강력하게 입력합니다. 서명과 일치하는 메소드 만 가리킬 수 있습니다.

4) 동시에 하나 이상의 방법을 가리킬 수 있습니다.


1

대표단은 주로 이벤트와 함께 사용됩니다.

필요한 것은 :

프로그램을 실행할 때 코드를 실행하고 싶지 않습니다. 프로그램을 실행 한 후 이벤트가 발생할 때마다 해당 코드를 실행하려고합니다.

예 :

  1. 콘솔 응용 프로그램 -코드는 프로그램을 실행할 때만 실행할 수 있습니다. (메인 방법으로 작성)
  2. Windows 응용 프로그램 (사용자 인터페이스 프로그래밍)-프로그램을 실행 한 후 버튼을 클릭하면 코드를 실행할 수 있습니다.

이것이 그들이 말하는 것입니다. 컴파일 할 때 어떤 메소드가 호출되는지 알 수 없습니다. 버튼을 클릭 할 때만 런타임에만 알 수 있습니다.

델리게이트가 없으면 사용자 인터페이스 프로그래밍이 불가능합니다. 사용자가 버튼을 클릭하고 텍스트 상자에 입력하고 드롭 다운 목록 항목 등을 선택하는 이벤트를 만들 때마다 코드를 실행하기 때문에 ...


0

대리인은 작업이 위임되는 대상입니다. 위임의 주요 목적은 코드를 분리하고 유연성과 재사용 성을 높이는 것입니다.

프로그래밍, 특히 객체 지향 프로그래밍에서 이는 일부 작업을 수행하기 위해 메서드를 호출 할 때 해당 객체가 참조하는 다른 객체의 메서드로 작업을 전달 함을 의미합니다. 객체가 사전 정의 된 메소드 세트를 준수하는 한 참조는 원하는 객체를 가리킬 수 있습니다. 이를 "인터페이스 프로그래밍"(구체적인 클래스 구현에 대한 프로그래밍)이라고합니다. 인터페이스는 기본적으로 일반적인 템플릿이며 구현이 없습니다. 그것은 단순히 요리법, 일련의 방법, 전제 조건 및 사후 조건 (규칙)을 의미합니다.

간단한 예 :

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

이제 당신은 SomeCaller에서 코드를 변경하지 않고 언제든지 원하는 구현을 사용할 수 있다는 것을 알았습니다. doIt()전달 된 유형 은 인터페이스이기 때문에 구체적이지 않고 추상적이기 때문입니다. Java 세계에서 이는 종종 서비스 (특정 인터페이스를 통해 서비스로 객체를 광고하는 객체)를 호출하는 서비스 패러다임에서 표현되며 서비스는 델리게이트가 작업을 수행하도록 도와달라고 요청합니다. 이 서비스의 메소드는 대략적인 작업 (makePayment (), createNewUser () 등)으로 이름이 지정되어 있지만 내부적으로 위임을 통해 문제가 해결되면 대의원 유형이 구체적인 구현 대신 인터페이스로 사용됩니다.

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(NB : 구현이 할당되는 방법은이 스레드의 범위를 벗어납니다. 제어 및 종속성 주입의 조회 반전.)


-2

실제로 "함수 포인터"는 아니지만 델리게이트는 다음과 같은 동적 언어처럼 보일 수 있습니다.



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

또는 JavaScript에서 다음과 같은 작업을 수행 할 수 있습니다.


var func = function(){ alert('foo!'); }
func();


2
이것은 위임의 예가 아닙니다. 귀하의 예에서는 기본적으로 변수가 참조하는 문자열과 이름이 같은 함수를 찾는 변수 함수라는 것을 사용하고 있습니다. 변수 함수보기 : php.net/manual/en/functions.variable-functions.php
Aquarelle
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.