programing

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

nasanasas 2020. 10. 2. 22:31
반응형

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

를 인수로 사용하고 다음을 반환하는 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);
}

For sharing an as complete as possible solution, I'm going to end up with presenting three different ways of doing, but now I'm going to start from the most basic principle.


Brief introduction

모든 CLR ( 공용 언어 런타임 ) 언어 (예 : C # 및 Visual Basic) 는 C 및 C ++ (기계 코드로 직접 컴파일 됨)와 같은 기본 언어보다 높은 수준에서 코드를 실행하는 CLI ( 공용 언어 인터프리터 ) 라는 VM에서 작동합니다. . 메서드는 어떤 종류의 컴파일 된 블록도 아니지만 CLR이 인식하고 본문을 꺼내 기계어 코드의 인라인 명령으로 되 돌리는 데 사용하는 구조화 된 요소 일뿐입니다. 따라서 메서드가 자체적으로 값을 생성하지 않기 때문에 메서드를 매개 변수로 전달할 수는 없습니다. 유효한식이 아닙니다! 따라서 대리자 개념을 우연히 발견하게 될 것입니다.


대리인이란 무엇입니까?

대리자는 메서드에 대한 포인터를 나타냅니다. 위에서 말했듯이 메서드는 값이 아니므로 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. 이 솔루션의 문제는 메서드 정의에있는 유형으로 제한하지 않고 인수를 동적으로 전달할 때 코드가 확인되지 않는다는 것입니다.

  • Way 2/3 Besides the Delegate special class, the delegates concept spreads to custom delegates, which are definitions of methods preceeded by the delegate keyword and they behave the same as normal methods. They are hence checked, and you'll come up with a "safe" code.

Look at the following example:

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

A second option not to write your own custom delegate is using one of them already defined within the framework:

  • Action wraps up a void with no arguments.
  • Action<T1> wraps up a void with one argument.
  • Action<T1, T2> wraps up a void with two arguments.
  • And so on...
  • Func<TR> wraps up a function with TR return type and with no arguments.
  • Func<T1, TR> wraps up a function with TR return type and with one argument.
  • Func<T1, T2, TR> wraps up a function with TR return type and with two arguments.
  • And so on...

(The latter solution is the one most people posted.)


If you want the ability to change which method is called at run time I would recommend using a delegate: http://www.codeproject.com/KB/cs/delegates_step1.aspx

It will allow you to create an object to store the method to call and you can pass that to your other methods when it's needed.


While the accepted answer is absolutely correct, I would like to provide an additional method.

I ended up here after doing my own searching for a solution to a similar question. I am building a plugin driven framework, and as part of it I wanted people to be able to add menu items to the applications menu to a generic list without exposing an actual Menu object because the framework may deploy on other platforms that don't have Menu UI objects. Adding general info about the menu is easy enough, but allowing the plugin developer enough liberty to create the callback for when the menu is clicked was proving to be a pain. Until it dawned on me that I was trying to re-invent the wheel and normal menus call and trigger the callback from events!

So the solution, as simple as it sounds once you realize it, eluded me until now.

Just create separate classes for each of your current methods, inherited from a base if you must, and just add an event handler to each.


Here is an example Which can help you better to understand how to pass a function as a parameter.

Suppose you have Parent page and you want to open a child popup window. In the parent page there is a textbox that should be filled basing on child popup textbox.

Here you need to create a delegate.

Parent.cs // declaration of delegates public delegate void FillName(String FirstName);

Now create a function which will fill your textbox and function should map delegates

//parameters
public void Getname(String ThisName)
{
     txtname.Text=ThisName;
}

Now on button click you need to open a Child popup window.

  private void button1_Click(object sender, RoutedEventArgs e)
  {
        ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor

         p.Show();

    }

IN ChildPopUp constructor you need to create parameter of 'delegate type' of parent //page

ChildPopUp.cs

    public  Parent.FillName obj;
    public PopUp(Parent.FillName objTMP)//parameter as deligate type
    {
        obj = objTMP;
        InitializeComponent();
    }



   private void OKButton_Click(object sender, RoutedEventArgs e)
    {


        obj(txtFirstName.Text); 
        // Getname() function will call automatically here
        this.DialogResult = true;
    }

Here is an example without a parameter: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string

with params: http://www.daniweb.com/forums/thread98148.html#

you basically pass in an array of objects along with name of method. you then use both with the Invoke method.

params Object[] parameters


If you want to pass Method as parameter, use:

using System;

public void Method1()
{
    CallingMethod(CalledMethod);
}

public void CallingMethod(Action method)
{
    method();   // This will call the method that has been passed as parameter
}

public void CalledMethod()
{
    Console.WriteLine("This method is called by passing parameter");
}

class PersonDB
{
  string[] list = { "John", "Sam", "Dave" };
  public void Process(ProcessPersonDelegate f)
  {
    foreach(string s in list) f(s);
  }
}

The second class is Client, which will use the storage class. It has a Main method that creates an instance of PersonDB, and it calls that object’s Process method with a method that is defined in the Client class.

class Client
{
  static void Main()
  {
    PersonDB p = new PersonDB();
    p.Process(PrintName);
  }
  static void PrintName(string name)
  {
    System.Console.WriteLine(name);
  }
}

참고URL : https://stackoverflow.com/questions/2082615/pass-method-as-parameter-using-c-sharp

반응형