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);
    }
}


답변

약간 다른 용도는 반사 속도를 높이는 것입니다. 즉, 매번 리플렉션을 사용하는 대신 Delegate.CreateDelegate메서드 (a MethodInfo)에 대한 (형식화 된) 대리자를 만들고 대신 해당 대리자를 호출하는 데 사용할 수 있습니다 . 이것은 다음입니다 많은 검사가 이미 수행 된 것처럼, 빨리 호출 당.

를 사용하면 Expression동일한 작업을 수행하여 즉석에서 코드를 만들 수도 있습니다. 예를 들어 Expression런타임에 선택한 유형에 대한 + 연산자를 나타내는를 쉽게 만들 수 있습니다 (언어가 제공하지 않는 제네릭에 대한 연산자 지원을 제공하기 위해). ; 를 Expression형식화 된 델리게이트로 컴파일 할 수 있습니다 .