Programing

대표단, 왜?

lottogame 2021. 1. 8. 07:43
반응형

대표단, 왜?


중복 가능성 :
언제 C #에서 대리자를 사용합니까?
대표자의 목적

대의원 사용과 관련하여 많은 질문을 보았습니다. 메서드를 직접 호출하는 대신 대리자를 사용하는 이유와 위치가 아직 명확하지 않습니다.

이 문구를 여러 번 들었습니다. "대리자 객체는 어떤 메서드가 호출 될지 컴파일 타임에 알 필요없이 참조 된 메서드를 호출 할 수있는 코드로 전달 될 수 있습니다."

나는 그 진술이 어떻게 정확한지 이해하지 못한다.

다음 예제를 작성했습니다. 동일한 매개 변수를 가진 3 개의 메소드가 있다고 가정 해 보겠습니다.

   public int add(int x, int y)
    {
        int total;
        return total = x + y;
    }
    public int multiply(int x, int y)
    {
        int total;
        return total = x * y;
    }
    public int subtract(int x, int y)
    {
        int total;
        return total = x - y;
    }

이제 대리자를 선언합니다.

public delegate int Operations(int x, int y);

이제 한 단계 더 나아가이 델리게이트 (또는 직접 델리게이트)를 사용하는 핸들러를 선언 할 수 있습니다.

전화 대리인 :

MyClass f = new MyClass();

Operations p = new Operations(f.multiply);
p.Invoke(5, 5);

또는 핸들러로 호출

f.OperationsHandler = f.multiply;
//just displaying result to text as an example
textBoxDelegate.Text = f.OperationsHandler.Invoke(5, 5).ToString();

이 두 경우 모두 "multiply"메서드가 지정되어 있습니다. 사람들이 "런타임시 기능 변경"또는 위의 문구를 사용하는 이유는 무엇입니까?

대리자를 선언 할 때마다 가리킬 메서드가 필요한데 대리자가 사용되는 이유는 무엇입니까? 가리킬 메서드가 필요한 경우 해당 메서드를 직접 호출하지 않는 이유는 무엇입니까? 그냥 함수를 직접 사용하는 것보다 대리자를 사용하려면 더 많은 코드를 작성해야하는 것 같습니다.

누군가 제게 실제 상황을 알려 주실 수 있습니까? 나는 완전히 혼란 스럽다.


런타임에 기능을 변경하는 것은 대리자가 수행하는 작업이 아닙니다.

기본적으로 델리게이트는 타이핑의 허름한 부담을 덜어줍니다.

예를 들면 :

class Person
{
    public string Name { get; }
    public int Age { get; }
    public double Height { get; }
    public double Weight { get; }
}

IEnumerable<Person> people = GetPeople();

var orderedByName = people.OrderBy(p => p.Name);
var orderedByAge = people.OrderBy(p => p.Age);
var orderedByHeight = people.OrderBy(p => p.Height);
var orderedByWeight = people.OrderBy(p => p.Weight);

상기 코드의에서는 p => p.Name, p => p.Age등을 평가하는 모든 람다 표현식 Func<Person, T>대표 (여기서 T이고 string, int, double, 및 double, 각각).

이제 델리게이트 없이 어떻게 위의 것을 달성 할 수 있었는지 생각해 봅시다 . OrderBy메서드가 대리자 매개 변수 를 사용하는 대신 일반성을 포기하고 다음 메서드를 정의해야합니다.

public static IEnumerable<Person> OrderByName(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByAge(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByHeight(this IEnumerable<Person> people);
public static IEnumerable<Person> OrderByWeight(this IEnumerable<Person> people);

이것은 완전히 짜증날 것 입니다. 첫째, 코드는 해당 Person유형의 컬렉션에만 적용되므로 재사용 가능성이 무한히 낮아졌습니다 . 또한 동일한 코드를 4 번 복사하여 붙여 넣어야합니다. 각 복사본에서 1 줄 또는 2 줄만 변경해야합니다 (관련 속성 Person이 참조되는 경우-그렇지 않으면 모두 동일하게 보입니다)! 이것은 빠르게 유지 관리 할 수없는 혼란이 될 것입니다.

따라서 델리게이트를 사용하면 코드 내에서 전환 할 수있는 특정 동작을 추상화 하여 코드를 더 재사용 하고 유지 관리 할 수 ​​있습니다.


.NET 대표자 : AC # 취침 이야기


델리게이트는 특히 linq와 클로저를 도입 한 후에 매우 유용합니다.

좋은 예는 표준 linq 메서드 중 하나 인 'Where'함수입니다. 'Where'는 목록과 필터를 가져 와서 필터와 일치하는 항목의 목록을 반환합니다. (필터 인수는 T를 취하고 부울을 반환하는 대리자입니다.)

대리자를 사용하여 필터를 지정하기 때문에 Where 함수는 매우 유연합니다. 예를 들어 홀수와 소수를 필터링하기 위해 다른 Where 함수가 필요하지 않습니다. 호출 구문도 매우 간결합니다. 인터페이스 나 추상 클래스를 사용한 경우에는 그렇지 않습니다.

좀 더 구체적으로 말하자면, 대리인을받는 것은 다음과 같이 작성할 수 있음을 의미합니다.

var result = list.Where(x => x != null);
...

대신 :

var result = new List<T>();
foreach (var e in list)
    if (e != null)
        result.add(e)
...

델리게이트를 선언 할 때마다 가리킬 메서드가 필요한데 왜 델리게이트가 사용됩니까? 가리킬 메서드가 필요한 경우 해당 메서드를 직접 호출하지 않는 이유는 무엇입니까?

인터페이스와 마찬가지로 델리게이트를 사용하면 코드를 분리하고 일반화 할 수 있습니다. 일반적으로 어떤 메서드를 실행할지 미리 알지 못하는 경우- 특정 서명과 일치하는 것을 실행해야 한다는 사실 만 알고있는 경우 대리자를 사용 합니다.

예를 들어 일정한 간격으로 일부 메서드를 실행하는 타이머 클래스를 생각해보십시오.

public delegate void SimpleAction();

public class Timer {
    public Timer(int secondsBetweenActions, SimpleAction simpleAction) {}
}

타이머에 무엇이든 연결할 수 있으므로 사용 방법을 예측하지 않고 현재 생각하고있는 소수의 시나리오로 사용을 제한하지 않고 다른 프로젝트 또는 애플리케이션에서 사용할 수 있습니다 .


예를 들어 보겠습니다. 클래스가를 노출하는 경우 event런타임에 몇 개의 델리게이트를 할당 할 수 있으며, 이는 어떤 일이 발생했음을 알리기 위해 호출됩니다. 수업을 작성할 때 어떤 델리게이트가 실행 될지 전혀 몰랐습니다. 대신, 이것은 클래스를 사용하는 사람에 의해 결정됩니다.


구체적인 예를 들자면, 특히 최근에 저를 위해 대리자를 사용 SendAsync()했습니다 System.Net.Mail.SmtpClient. 엄청나게 많은 이메일을 보내는 응용 프로그램이 있는데 Exchange 서버가 메시지를 받아들이기를 기다리는 동안 눈에 띄는 성능 저하가 발생했습니다. 그러나 해당 서버와의 상호 작용 결과를 기록해야했습니다.

그래서 저는 그 로깅을 처리하는 델리게이트 메서드를 작성하고 각 이메일을 보낼 때 ( SendAsync()이전에 사용했던)에 전달했습니다 Send(). 이렇게하면 결과를 기록하기 위해 델리게이트를 콜백 할 수 있으며 애플리케이션 스레드는 계속하기 전에 상호 작용이 완료 될 때까지 기다리지 않습니다.

상호 작용이 완료 될 때까지 기다리지 않고 애플리케이션을 계속하려는 모든 외부 IO에 대해서도 마찬가지입니다. 웹 서비스 등에 대한 프록시 클래스는이를 활용합니다.


a delegate가 필요한 한 가지 예 는 UI 스레드에서 컨트롤을 수정해야하고 다른 스레드에서 작업하는 경우입니다. 예를 들면

public delegate void UpdateTextBox(string data);

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    ...
    Invoke(new UpdateTextBox(textBoxData), data);
    ...

}

private void textBoxData(string data)
{
            textBox1.Text += data;
}

예에서 변수에 대리자를 할당하면 다른 변수처럼 전달할 수 있습니다. 대리자를 매개 변수로 받아들이는 메서드를 만들 수 있으며 메서드가 실제로 선언 된 위치를 알 필요없이 대리자를 호출 할 수 있습니다.

private int DoSomeOperation( Operations operation )
{
    return operation.Invoke(5,5);
}

...

MyClass f = new MyClass();
Operations p = new Operations(f.multiply);
int result = DoSomeOperation( p );

대리자는 메서드를 int와 같은 방식으로 전달할 수있는 것으로 만듭니다. 변수는 당신에게 아무것도주지 않는다고 말할 수 있습니다.

int i = 5;
Console.Write( i + 10 );

값 5가 지정되는 것을 볼 수 있으므로 Console.Write( 5 + 10 ). 그 경우는 사실이지만 말할 수있는 혜택을 놓친다

DateTime nextWeek = DateTime.Now.AddDays(7);

특정 DateTime.AddSevenDays()메서드, 메서드 등 을 정의 할 AddSixDays필요가 없습니다.


대리자를 사용하여 구독 및 eventHandler를 구현할 수 있습니다. 또한 (끔찍한 방식으로) 순환 종속성을 피하기 위해 사용할 수 있습니다.

Or if you have a calculation engine and there are many possible calculations, then you can use a parameter delegate instead of many different function calls for your engine.


Did you read http://msdn.microsoft.com/en-us/library/ms173171(VS.80).aspx ?


Using your example of Operations, imagine a calculator which has several buttons. You could create a class for your button like this

class CalcButton extends Button {
   Operations myOp;
   public CalcButton(Operations op) {
      this.myOp=op; 
   }
   public void OnClick(Event e) {
      setA( this.myOp(getA(), getB()) ); // perform the operation
   }
}

and then when you create buttons, you could create each with a different operation

CalcButton addButton = new CalcButton(new Operations(f.multiply));

This is better for several reasons. You don't replicate the code in the buttons, they are generic. You could have multiple buttons that all have the same operation, for example on different panels or menus. You could change the operation associated with a button on the fly.


Delegates are used to solve an Access issue. When ever you want to have object foo that needs to call object bar's frob method but does not access to to frob method.

Object goo does have access to both foo and bar so it can tie it together using delegates. Typically bar and goo are often the same object.

For example a Button class typically doesn't have any access to the class defines a Button_click method.

So now that we have that we can use it for a whole lot things other than just events. Asynch patterns and Linq are two examples.


It seems many of the answers have to do with inline delegates, which in my opinion are easier to make sense of than what I'll call "classic delegates."

Below is my example of how delegates allow a consuming class to change or augment behaviour (by effectively adding "hooks" so a consumer can do things before or after a critical action and/or prevent that behaviour altogether). Notice that all of the decision-making logic is provided from outside the StringSaver class. Now consider that there may be 4 different consumers of this class -- each of them can implement their own Verification and Notification logic, or none, as appropriate.

internal class StringSaver
{
    public void Save()
    {
        if(BeforeSave != null)
        {
            var shouldProceed = BeforeSave(thingsToSave);
            if(!shouldProceed) return;
        }
        BeforeSave(thingsToSave);

        // do the save

        if (AfterSave != null) AfterSave();
    }

    IList<string> thingsToSave;
    public void Add(string thing) { thingsToSave.Add(thing); }

    public Verification BeforeSave;
    public Notification AfterSave;
}

public delegate bool Verification(IEnumerable<string> thingsBeingSaved);
public delegate void Notification();

public class SomeUtility
{
    public void SaveSomeStrings(params string[] strings)
    {
        var saver = new StringSaver
            {
                BeforeSave = ValidateStrings, 
                AfterSave = ReportSuccess
            };

        foreach (var s in strings) saver.Add(s);

        saver.Save();
    }

    bool ValidateStrings(IEnumerable<string> strings)
    {
        return !strings.Any(s => s.Contains("RESTRICTED"));
    }

    void ReportSuccess()
    {
        Console.WriteLine("Saved successfully");
    }
}

I guess the point is that the method to which the delegate points is not necessarily in the class exposing the delegate member.

ReferenceURL : https://stackoverflow.com/questions/3567478/delegates-why

반응형