development

C #에서 함수를 매개 변수로 전달하는 방법은 무엇입니까?

big-blog 2021. 1. 6. 20:42
반응형

C #에서 함수를 매개 변수로 전달하는 방법은 무엇입니까?


C #에서 매개 변수로 함수를 전달할 수 있습니까? Func 또는 Action 클래스를 사용하여 수행 할 수 있지만 이로 인해 전체 함수 서명을 한 번에 선언해야합니다. Delegate를 사용하려고하면 메서드 그룹을 Delegate로 변환 할 수 없다는 컴파일 오류가 발생합니다.

저는 Axial에서 작업 중이며 사용자가 웹 서비스를 호출하도록 허용하려고합니다. 내가하려는 것은 Visual Studio 프록시 클래스를 만든 다음 생성 된 함수를 전달하는 기능입니다. 생성 된 코드는 함수 이름 만 사용하므로 함수 서명은 중요하지 않습니다. 그러나 웹 서비스가 없거나 Visual Studio에서 업데이트 된 경우 프록시의 Url 속성을 사용하는 기능과 컴파일러 오류라는 두 가지 이유로 이름 대신 함수를 전달하고 싶습니다.


public void AlertIt(object o) {
    Axial.DOM.Window.Alert(o.ToString());
}
public void CallAddService() {
    object[] param = new object[] { int.Parse(txtA.Text), int.Parse(txtB.Text) };
    Axial.ServerScript.CallWebService(new WSProxy.WS().Add, param, AlertIt, AlertIt);
}

class Axial.ServerScript {
    public void CallWebService(Delegate method, object[] param, Action<object> successCallback, Action<object> failureCallback) {
        // translate to javascript (already working)
    }
}

나는 당신이 원하는 것은 다음과 같습니다.

static object InvokeMethod(Delegate method, params object[] args){
    return method.DynamicInvoke(args);
}

static int Add(int a, int b){
    return a + b;
}

static void Test(){
    Console.WriteLine(InvokeMethod(new Func<int, int, int>(Add), 5, 4));
}

"9"를 인쇄합니다.


메서드 그룹, 익명 메서드 또는 람다 식을 대리자로 변환하려면 컴파일러가 정확한 대리자 형식을 알고 있어야합니다. 그러나 잠재적으로 람다 식과 캡처 된 변수를 사용하여 더 간단하게 만들 수 있습니다.

public void InvokeMethod(Action action)
{
    action();
}

public int Add(int a, int b)
{
    return a + b;
}

public void Test()
{    
    InvokeMethod(() => Add(2, 3));
}

이는 기본적으로 정상적인 방식으로 호출을 지연하지만 실제 호출을 Add일반 Action델리게이트 로 래핑합니다 .

이것이 귀하의 요구 사항을 충족하지 못하는 경우, 귀하가 실제로 달성하려는 목표에 대해 좀 더 자세히 알려 주실 수 있습니다.

편집 : 이것이 생성 된 코드 인 경우, Func<...>너무 많지 않다고 가정하고 올바른 유형 인수로 캐스트 할 수 있습니다 . 그 외에는 메소드 그룹을 전달하는 실제 방법이 없습니다. MemberInfo를 제공하는 "infoof (...)"연산자 (typeof와 같지만 멤버에 대한)에 대한 호출이 가끔 있었지만 실제로는 존재하지 않습니다.


먼저 대리인이 있어야합니다.

delegate int Operation(int a, int b)

그러면 다음과 같이됩니다.

public void InvokeMethod(Operation method, object target, object param)
{
    method((int) target, (int) param);
}

Invoke를 호출 할 필요가 없습니다.

dbone과 마찬가지로 params [] 배열이 필요한 이유를 잘 모르겠습니다. 매개 변수의 확장 된 사용법을 명확히 하시겠습니까?

또한 컴파일 오류가 발생하기 때문에 질문을 수정해야합니다.


여기 대리자를 사용하는 것이 좋은 예입니다.

대표자 예

반사를 사용하는 이유는 무엇입니까? 다른 수의 매개 변수가있을 수 있습니까? 또는 메서드 서명이 일정하게 유지된다는 것을 알고 있습니까 (또한 C #에서 params [] 키워드를 지원함을 기억하십시오)

매개 변수 C #

HTH


Justin Etheredge의 Functional Programming Series살펴보십시오 . 거기에서 문제에 대한 해결책을 찾아야합니다.


이것은 ( C / C ++ / VB.NET/Python ) -style pass function by pointer / ref (with C # delegate )에 이미 익숙한 프로그래머에게 매우 간단한 예제입니다 .

        delegate void CALLBACK(String s);
        static void Main(string[] args)
        {

            Get("some string", testfunc);

            Util.pause();
        }

        static void Get(String s, CALLBACK x)
        {
            x(s);
        }


        static void testfunc(String s)
        {
            Console.WriteLine(s);
        }

Say If you need to pass the method as parameter as well as you need to catch the return value for further processing . Then the above examples will work fine . But say if you need to pass a method with void return type then you need to create one more version of the InvokeMethod function. Check the example below.

private static T retry<T>(Delegate method, params object[] args)
{
    for (int i = 0; i <= 3; i++)
    {
        try
        {
            return (T)method.DynamicInvoke(args);
        }
        catch (Exception ex)
        {
            if (i == 3)
            {
                logMessage(ex.Message);
            }
            Console.WriteLine("Retry count " + i);
            Thread.Sleep(10);
        }
    }
    return default(T);
}

private static void retry2(Delegate method, params object[] args)
{
    for (int i = 0; i <= 3; i++)
    {
        try
        {
            method.DynamicInvoke(args);
            break;
        }
        catch (Exception ex)
        {
            if (i == 3)
            {
                logMessage(ex.Message);
                //return default(T);
            }
            Console.WriteLine("Retry count " + i);
            Thread.Sleep(10);
        }
    }
}
static bool isSuccess = true;
static void logMessage(string msg)
{
    isSuccess = false;
    Console.WriteLine(msg);
}

static int Add(int a, int b)
{
    return a + b;
}

static void Add2(int a, int b)
{
    int c = a + b;
    Console.WriteLine(c);
}

static void Main(string[] args)
{
    int d = retry<int>(new Func<int, int, int>(Add), 6, 7.7);
    Console.Write("  " + d + "\n"+isSuccess);

    retry2(new Action<int, int>(Add2), 45, 60);

    Console.ReadKey();
}

Something like this ought to work for you:

delegate int MyDelegate(int a, int b);
public int Add(int a, int b) {
    return a + b;
}
public void InvokeMethod(Delegate method, object[] param) {
    Console.WriteLine(method.DynamicInvoke(param));
}
public Form1() {       
    InitializeComponent();
    InvokeMethod(new MyDelegate(Add), new object[] { 1, 2 });
}

Good luck!

ReferenceURL : https://stackoverflow.com/questions/380198/how-to-pass-a-function-as-a-parameter-in-c

반응형