[C#] C #을 사용하여 메소드를 매개 변수로 전달

동일한 서명 (매개 변수 및 반환 값)을 가진 여러 가지 방법이 있지만 이름과 방법의 내부가 다릅니다. 전달 된 메소드를 호출하는 다른 메소드로 실행할 메소드 이름을 전달하고 싶습니다.

public int Method1(string)
{
    ... do something
    return myInt;
}

public int Method2(string)
{
    ... do something different
    return myInt;
}

public bool RunTheMethod([Method Name passed in here] myMethodName)
{
    ... do stuff
    int i = myMethodName("My String");
    ... do more stuff
    return true;
}

public bool Test()
{
    return RunTheMethod(Method1);
}

이 코드는 작동하지 않지만 이것이 내가하려고하는 것입니다. 내가 이해하지 못하는 것은 매개 변수를 정의해야하기 때문에 RunTheMethod 코드를 작성하는 방법입니다.



답변

.net 3.5의 Func 델리게이트를 RunTheMethod 메서드의 매개 변수로 사용할 수 있습니다. Func 델리게이트를 사용하면 특정 유형의 여러 매개 변수를 사용하고 특정 유형의 단일 인수를 리턴하는 메소드를 지정할 수 있습니다. 다음은 작동해야하는 예입니다.

public class Class1
{
    public int Method1(string input)
    {
        //... do something
        return 0;
    }

    public int Method2(string input)
    {
        //... do something different
        return 1;
    }

    public bool RunTheMethod(Func<string, int> myMethodName)
    {
        //... do stuff
        int i = myMethodName("My String");
        //... do more stuff
        return true;
    }

    public bool Test()
    {
        return RunTheMethod(Method1);
    }
}


답변

대리자 를 사용해야합니다 . 이 경우 모든 메소드는 string매개 변수를 가져 와서 반환합니다 int. 이것은 가장 간단하게 Func<string, int>대리자 1로 표시됩니다 . 따라서 다음과 같이 간단한 변경만으로 코드가 정확해질 수 있습니다.

public bool RunTheMethod(Func<string, int> myMethodName)
{
    // ... do stuff
    int i = myMethodName("My String");
    // ... do more stuff
    return true;
}

대표자들은 이것보다 훨씬 더 많은 힘을 가지고 있습니다. 예를 들어 C #을 사용하면 람다 식에서 대리자를 만들 수 있으므로 다음과 같은 방법으로 메서드를 호출 할 수 있습니다.

RunTheMethod(x => x.Length);

다음과 같은 익명 함수가 생성됩니다.

// The <> in the name make it "unspeakable" - you can't refer to this method directly
// in your own code.
private static int <>_HiddenMethod_<>(string x)
{
    return x.Length;
}

그런 다음 해당 대리자를 RunTheMethod메서드에 전달하십시오 .

이벤트 구독, 비동기 실행, 콜백-모든 종류의 델리게이트를 사용할 수 있습니다. LINQ를 사용하려는 경우 특히 읽을 가치가 있습니다. 나는이 기사 입니다 주로 대표와 이벤트 사이의 차이점에 대해,하지만 당신은 그것을 유용한 어쨌든을 찾을 수 있습니다.


1 이것은 Func<T, TResult>프레임 워크 의 일반 델리게이트 유형을 기반으로합니다 . 당신은 쉽게 자신을 선언 할 수 있습니다 :

public delegate int MyDelegateType(string value)

그런 다음 MyDelegateType대신 매개 변수를 유형으로 만드십시오 .


답변

OP의 예에서 :

 public static int Method1(string mystring)
 {
      return 1;
 }

 public static int Method2(string mystring)
 {
     return 2;
 }

Action Delegate를 시도 할 수 있습니다! 그런 다음 사용하여 메소드를 호출하십시오.

 public bool RunTheMethod(Action myMethodName)
 {
      myMethodName();   // note: the return value got discarded
      return true;
 }

RunTheMethod(() => Method1("MyString1"));

또는

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

그런 다음 단순히 메소드를 호출하십시오.

Console.WriteLine(InvokeMethod(new Func<string,int>(Method1), "MyString1"));

Console.WriteLine(InvokeMethod(new Func<string, int>(Method2), "MyString2"));


답변

public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}

용법:

var ReturnValue = Runner(() => GetUser(99));


답변

가능한 한 완전한 솔루션을 공유하기 위해 세 가지 다른 방법을 제시하지만 이제는 가장 기본적인 원칙부터 시작하겠습니다.


간단한 소개

C #, F # 및 Visual Basic과 같은 CLR ( 공용 언어 런타임 )에서 실행되는 모든 언어 는 VM에서 작동하며 C 및 C ++와 같은 기본 언어 (기계로 직접 컴파일)보다 높은 수준에서 코드를 실행합니다. 암호). 메소드는 어떤 종류의 컴파일 된 블록이 아니라 CLR이 인식하는 구조화 된 요소 일뿐입니다. 따라서 메소드는 표현식이 아니므로 자체적으로 값을 생성하지 않으므로 메소드를 매개 변수로 전달할 수 없습니다. 오히려 이들은 생성 된 CIL 코드에 정의 된 명령문입니다. 따라서 델리게이트 개념에 직면하게됩니다.


대리인은 무엇입니까?

델리게이트는 메소드에 대한 포인터를 나타냅니다. 위에서 말했듯이 메소드는 가치가 없으므로 CLR 언어에는 특수 클래스가있어 Delegate모든 메소드를 마무리합니다.

다음 예를보십시오.

static void MyMethod()
{
    Console.WriteLine("I was called by the Delegate special class!");
}

static void CallAnyMethod(Delegate yourMethod)
{
    yourMethod.DynamicInvoke(new object[] { /*Array of arguments to pass*/ });
}

static void Main()
{
    CallAnyMethod(MyMethod);
}

세 가지 다른 방법, 같은 개념 뒤에 :

  • 방법 1 위의 예와 같이 특수 클래스를 직접
    사용하십시오 Delegate. 이 솔루션의 문제는 인수를 메소드 정의의 인수 유형으로 제한하지 않고 인수를 동적으로 전달함에 따라 코드가 선택 해제된다는 것입니다.

  • 방법 2 특수 클래스
    외에 Delegate대리자 개념은 delegate키워드가 앞에 오는 메서드의 정의 인 사용자 지정 대리자로 확산 되며 일반 메서드와 동일하게 동작합니다. 이것에 의해 확인되므로 완벽하게 안전한 코드를 얻을 수 있습니다.

    예를 들면 다음과 같습니다.

    delegate void PrintDelegate(string prompt);
    
    static void PrintSomewhere(PrintDelegate print, string prompt)
    {
        print(prompt);
    }
    
    static void PrintOnConsole(string prompt)
    {
        Console.WriteLine(prompt);
    }
    
    static void PrintOnScreen(string prompt)
    {
        MessageBox.Show(prompt);
    }
    
    static void Main()
    {
        PrintSomewhere(PrintOnConsole, "Press a key to get a message");
        Console.Read();
        PrintSomewhere(PrintOnScreen, "Hello world");
    }
  • 방법 3
    또는 .NET 표준 내에 이미 정의 된 대리자를 사용할 수도 있습니다.

    • Actionvoid인수없이 마무리합니다 .
    • Action<T1>void하나의 인수로 마무리합니다 .
    • Action<T1, T2>void두 개의 인수로 마무리합니다 .
    • 등등…
    • Func<TR>TR반환 유형과 인수가없는 함수를 마무리합니다 .
    • Func<T1, TR>TR반환 유형과 하나의 인수 로 함수를 마무리합니다 .
    • Func<T1, T2, TR>TR반환 유형과 두 개의 인수 로 함수를 마무리합니다 .
    • 등등…

후자의 솔루션은 대부분의 사람들이 게시 한 솔루션입니다.


답변

인수로 사용하고 :를 반환하는 Func<string, int>함수를 나타내는 대리자를 사용해야 string합니다 int.

public bool RunTheMethod(Func<string, int> myMethod) {
    // do stuff
    myMethod.Invoke("My String");
    // do stuff
    return true;
}

그런 다음 사용하십시오.

public bool Test() {
    return RunTheMethod(Method1);
}


답변

런타임에 호출되는 메소드를 변경하려면 위임을 사용하는 것이 좋습니다. http://www.codeproject.com/KB/cs/delegates_step1.aspx

호출 할 메소드를 저장할 오브젝트를 작성하고 필요할 때이를 다른 메소드에 전달할 수 있습니다.