Programming

C #에서 대리자를 언제 사용합니까?

procodes 2020. 8. 17. 11:37
반응형

C #에서 대리자를 언제 사용합니까? [닫은]


C #에서 델리게이트를 어떻게 사용합니까?


이제 C #에 람다 식과 익명 메서드가 있으므로 대리자를 훨씬 더 많이 사용합니다. 논리를 구현하기 위해 항상 별도의 메서드가 있어야하는 C # 1에서는 대리자를 사용하는 것이 종종 의미가 없었습니다. 요즘에는 다음을 위해 대리자를 사용합니다.

  • 이벤트 핸들러 (GUI 등)
  • 스레드 시작
  • 콜백 (예 : 비동기 API)
  • LINQ 및 유사 (List.Find 등)
  • 내부에 특수 논리가 포함 된 "템플릿"코드를 효과적으로 적용하려는 다른 곳 (대리자가 전문화를 제공하는 곳)

대리인은 여러 목적에 매우 유용합니다.

이러한 목적 중 하나는 데이터 시퀀스를 필터링하는 데 사용하는 것입니다. 이 경우 하나의 인수를 받아들이고 대리자 자체의 구현에 따라 true 또는 false를 반환하는 조건 자 대리자를 사용합니다.

여기에 어리석은 예가 있습니다. 이것에서 좀 더 유용한 것을 외삽 할 수 있다고 확신합니다.

using System;
using System.Linq;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<String> names = new List<String>
        {
            "Nicole Hare",
            "Michael Hare",
            "Joe Hare",
            "Sammy Hare",
            "George Washington",
        };

        // Here I am passing "inMyFamily" to the "Where" extension method
        // on my List<String>.  The C# compiler automatically creates 
        // a delegate instance for me.
        IEnumerable<String> myFamily = names.Where(inMyFamily);

        foreach (String name in myFamily)
            Console.WriteLine(name);
    }

    static Boolean inMyFamily(String name)
    {
        return name.EndsWith("Hare");
    }
}

또 다른 흥미로운 답변을 찾았습니다.

동료가 방금이 질문을했습니다. .NET에서 대리인의 요점은 무엇입니까? 내 대답은 매우 짧았고 그가 온라인에서 찾지 못한 것은 방법의 실행을 지연시키는 것이었다.

출처 : LosTechies

LINQ가하는 것처럼.


대리자를 사용하여 함수 유형 변수 및 매개 변수를 선언 할 수 있습니다.

"자원 차용"패턴을 고려하십시오. 클라이언트 코드가 그 사이에 리소스를 "차용"하도록 허용하면서 리소스 생성 및 정리를 제어하려고합니다.

이것은 대리자 형식을 선언합니다.

public delegate void DataReaderUser( System.Data.IDataReader dataReader );

이 서명과 일치하는 모든 메서드를 사용하여이 형식의 대리자를 인스턴스화 할 수 있습니다. C # 2.0에서는 메서드 이름을 사용하거나 익명 메서드를 사용하여 암시 적으로이 작업을 수행 할 수 있습니다.

이 메소드는 유형을 매개 변수로 사용합니다. 대리자의 호출을 확인합니다.

public class DataProvider
{
    protected string _connectionString;

    public DataProvider( string psConnectionString )
    {
        _connectionString = psConnectionString;
    }

    public void UseReader( string psSELECT, DataReaderUser readerUser )
    {
        using ( SqlConnection connection = new SqlConnection( _connectionString ) )
        try
        {
            SqlCommand command = new SqlCommand( psSELECT, connection );
            connection.Open();
            SqlDataReader reader = command.ExecuteReader();

            while ( reader.Read() )
                readerUser( reader );  // the delegate is invoked
        }
        catch ( System.Exception ex )
        {
            // handle exception
            throw ex;
        }
    }
}

다음과 같이 익명 메서드로 함수를 호출 할 수 있습니다. 익명 메소드는 변수를 사용할 수 있습니다 선언 외부 자체. 이것은 매우 편리합니다 (예제는 약간 인위적이지만).

string sTableName = "test";
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'";

DataProvider.UseReader( sQuery,
    delegate( System.Data.IDataReader reader )
    {
        Console.WriteLine( sTableName + "." + reader[0] );
    } );

델리게이트는 종종 하나의 방법으로 인터페이스 대신 사용될 수 있습니다. 일반적인 예로 관찰자 패턴이 있습니다. 다른 언어에서는 어떤 일이 발생했다는 알림을 받으려면 다음과 같이 정의 할 수 있습니다.

class IObserver{ void Notify(...); }

C #에서는 핸들러가 대리자 인 이벤트를 사용하여 더 일반적으로 표현됩니다. 예를 들면 다음과 같습니다.

myObject.SomeEvent += delegate{ Console.WriteLine("..."); };

예를 들어 목록에서 항목 집합을 선택하는 경우와 같이 조건자를 함수에 전달해야하는 경우 대리자를 사용하는 또 다른 좋은 장소 :

myList.Where(i => i > 10);

위는 다음과 같이 작성할 수도있는 람다 구문의 예입니다.

myList.Where(delegate(int i){ return i > 10; });

대리자를 사용하는 것이 유용 할 수있는 또 다른 위치는 다음과 같이 팩토리 함수를 등록하는 것입니다.

myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);

이게 도움이 되길 바란다!


나는 이것에 대해 정말로 늦게 들어 왔지만, 오늘 델리게이트의 목적을 파악하는 데 어려움을 겪었고 그들의 목적을 잘 설명하는 것과 동일한 결과를 제공하는 두 개의 간단한 프로그램을 작성했습니다.

NoDelegates.cs

using System;

public class Test {
    public const int MAX_VALUE = 255;
    public const int MIN_VALUE = 10;

    public static void checkInt(int a) {
        Console.Write("checkInt result of {0}: ", a);
        if (a < MAX_VALUE && a > MIN_VALUE)
            Console.WriteLine("max and min value is valid");
        else
            Console.WriteLine("max and min value is not valid");
    }

    public static void checkMax(int a) {
        Console.Write("checkMax result of {0}: ", a);
        if (a < MAX_VALUE)
            Console.WriteLine("max value is valid");
        else
            Console.WriteLine("max value is not valid");
    }

    public static void checkMin(int a) {
        Console.Write("checkMin result of {0}: ", a);
        if (a > MIN_VALUE)
            Console.WriteLine("min value is valid");
        else
            Console.WriteLine("min value is not valid");
        Console.WriteLine("");
    }
}

public class Driver {
    public static void Main(string [] args) {
        Test.checkInt(1);
        Test.checkMax(1);
        Test.checkMin(1);

        Test.checkInt(10);
        Test.checkMax(10);
        Test.checkMin(10);

        Test.checkInt(20);
        Test.checkMax(20);
        Test.checkMin(20);

        Test.checkInt(30);
        Test.checkMax(30);
        Test.checkMin(30);

        Test.checkInt(254);
        Test.checkMax(254);
        Test.checkMin(254);

        Test.checkInt(255);
        Test.checkMax(255);
        Test.checkMin(255);

        Test.checkInt(256);
        Test.checkMax(256);
        Test.checkMin(256);
    }
}

Delegates.cs

using System;

public delegate void Valid(int a);

public class Test {
    public const int MAX_VALUE = 255;
    public const int MIN_VALUE = 10;

    public static void checkInt(int a) {
        Console.Write("checkInt result of {0}: ", a);
        if (a < MAX_VALUE && a > MIN_VALUE)
            Console.WriteLine("max and min value is valid");
        else
            Console.WriteLine("max and min value is not valid");
    }

    public static void checkMax(int a) {
        Console.Write("checkMax result of {0}: ", a);
        if (a < MAX_VALUE)
            Console.WriteLine("max value is valid");
        else
            Console.WriteLine("max value is not valid");
    }

    public static void checkMin(int a) {
        Console.Write("checkMin result of {0}: ", a);
        if (a > MIN_VALUE)
            Console.WriteLine("min value is valid");
        else
            Console.WriteLine("min value is not valid");
        Console.WriteLine("");
    }
}

public class Driver {
    public static void Main(string [] args) {
        Valid v1 = new Valid(Test.checkInt);
        v1 += new Valid(Test.checkMax);
        v1 += new Valid(Test.checkMin);
        v1(1);
        v1(10);
        v1(20);
        v1(30);
        v1(254);
        v1(255);
        v1(256);
    }
}

A slightly different use is to speed up reflection; i.e. instead of using reflection each time, you can use Delegate.CreateDelegate to create a (typed) delegate to a method (a MethodInfo), and call that delegate instead. This is then much quicker per call, as the checks have already been done.

With Expression, you can also do the same to create code on the fly - for example, you can easily create an Expression that represents the + operator for a type chosen at runtime (to provide operator support for generics, which the language doesn't provide); and you can compile an Expression to a typed delegate - job done.


Delegates are used any time you use events - that's the mechanism by which they work.

In addition, delegates are very useful for things such as using LINQ queries. For example, many LINQ queries take a delegate (often Func<T,TResult>) which can be used for filtering.


subscribing eventhandlers to events


An example might be as seen here. You have a method to process an object that meets certain requirements. However, you want to be able to process the object in multiple ways. Instead of having to create separate methods, you can simply assign a matching method that processes the object to a delegate and pass the delegate to the method that selects the objects. That way, you can assign different methods to the one selector method. I tried to make this easily understandable.


I use delegates to communicate with threads.

For example, I might have a win forms app which downloads a file. The app starts a worker thread to do the download (which prevents the GUI from locking up). The worker thread uses delegates to send status messages (eg download progress) back to the main program, so that the GUI can update the status bar.


  1. For event handler

  2. To pass method in a method parameters


The first line of usage is to replace the Observer/Observable (events) pattern. The second, a nice elegant version of the Strategy pattern. Various other usages can be gathered, though more esoteric than these first two I think.


Events, other anynch operations


Any time you want to encapsulate behavior, but invoke it in a uniform way. Event Handlers, call-back functions, etc. You can accomplish similar things using Interfaces and casts, but sometimes, behavior isn't necessarily tied to a type or object. Sometimes you just have behavior you need to encapsulate.


Lazy parameter initialization! Besides all previous answers (strategy pattern, observer pattern, etc), delegates allow you to handle lazy initialization of parameters. For example, suppose you have a function Download() which takes quite a lot of time and returns a certain DownloadedObject. This object is consumed by a Storage depending on a certain Conditions. Typically, you would:

storage.Store(conditions, Download(item))

However, with delegates (more precisely, lambdas) you can do the following, by changing the signature of store so that it receives a Condition and a Func<Item,DownloadedObject> and use it like this:

storage.Store(conditions, (item) => Download(item))

Therefore, storage will only evaluate the delegate if necessary, executing download depending on Conditions.


Usage of delegates

  1. Event Handling
  2. Multi Casting

The comparison param in In Array.Sort(T[] array, Comparison comparison), List.Sort(Comparison comparison), etc


As far as I know, delegates can be converted to function pointers. This makes life MUCH easier when interoperating with native code that takes function pointers, as they can effectively be object-orientated, even though the original programmer didn't make any provision for that to happen.


Delegate's are used to call a method by it's reference. For example:

  delegate void del_(int no1,int no2);
class Math
{
   public static void add(int x,int y)
   {
     Console.WriteLine(x+y);
   }
   public static void sub(int x,int y)
   {
     Console.WriteLine(x-y);
   }
}



    class Program
    {
        static void Main(string[] args)
        {
            del_ d1 = new del_(Math.add);
            d1(10, 20);
            del_ d2 = new del_(Math.sub);
            d2(20, 10);
            Console.ReadKey();
        }
    }

참고URL : https://stackoverflow.com/questions/191153/when-would-you-use-delegates-in-c

반응형