Метод передачи в качестве параметра с использованием 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, так как мне нужно определить параметр.

Вы можете использовать делегат Func в .net 3.5 в качестве параметра в методе 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 myMethodName) { //... do stuff int i = myMethodName("My String"); //... do more stuff return true; } public bool Test() { return RunTheMethod(Method1); } } 

Вам нужно использовать делегат . В этом случае все ваши методы принимают string параметр и возвращают int – это наиболее просто представлено Func delegate 1 . Таким образом, ваш код может стать правильным с таким простым изменением, как это:

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

По правде говоря, у делегатов гораздо больше власти. Например, с C # вы можете создать делегат из выражения lambda , чтобы вы могли вызвать ваш метод таким образом:

 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 .

Вы можете использовать delegates для подписки на события, асинхронное выполнение, обратные вызовы – всевозможные вещи. Стоит их прочитать, особенно если вы хотите использовать LINQ. У меня есть статья, которая в основном касается различий между делегатами и событиями, но в любом случае вы можете найти ее полезной.


1 Это основано только на общий тип делегата Func в структуре; вы можете легко заявить о себе:

 public delegate int MyDelegateType(string value) 

и затем вместо параметра make будет иметь тип MyDelegateType .

Вы также можете попробовать Action Delegate!

  public static int Method1(string mystring) { return 1; } public static int Method2(string mystring) { return 2; } public bool RunTheMethod(Action myMethodName) { myMethodName(); return true; } 

Затем вызовите свой метод, используя

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

Или

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

Затем просто вызовите метод

 Console.WriteLine(InvokeMethod(new Func(Method1), "MyString1")); Console.WriteLine(InvokeMethod(new Func(Method2), "MyString2")); 
 public static T Runner(Func funcToRun) { //Do stuff before running function as normal return funcToRun(); } 

Применение:

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

Вы должны использовать делегат Func , представляющий функцию, принимающую string качестве аргумента и возвращающую int :

 public bool RunTheMethod(Func 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

Это позволит вам создать объект для хранения метода для вызова, и вы можете передать его другим методам, когда это необходимо.

Хотя принятый ответ абсолютно правильный, я хотел бы предоставить дополнительный метод.

Я оказался здесь после того, как стал искать решение аналогичного вопроса. Я создаю фреймворк, подключенный к плагину, и, как часть этого, я хотел, чтобы люди могли добавлять пункты меню в меню приложений в общий список, не подвергая действительный объект Menu поскольку среда может развертываться на других платформах, которые не имеют Menu UI объектов. Добавление общей информации о меню достаточно просто, но разрешение разработчику плагина достаточной свободы для создания обратного вызова при нажатии на меню оказалось болью. Пока меня не стало, что я пытался заново изобрести колесо и позвонить в обычное меню и вызвать ответный звонок из событий!

Поэтому решение, столь же простое, как кажется, когда вы это осознаете, ускользало от меня до сих пор.

Просто создайте отдельные classы для каждого из ваших текущих методов, унаследованных от базы, если нужно, и просто добавьте обработчик событий к каждому.

Вот пример, который поможет вам лучше понять, как передать функцию в качестве параметра.

Предположим, у вас есть родительская страница, и вы хотите открыть всплывающее окно для ребенка. На родительской странице есть текстовое поле, которое должно быть заполнено на основе текстового поля дочернего всплывающего windows.

Здесь вам нужно создать делегат.

Parent.cs // Объявление делегатов public delegate void FillName (String FirstName);

Теперь создайте функцию, которая заполнит ваше текстовое поле, а функция должна отображать delegates

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

Теперь при нажатии кнопки вам нужно открыть всплывающее окно Child.

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

В конструкторе ChildPopUp вам необходимо создать параметр «тип делегата» родительской // страницы

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

Чтобы поделиться как можно более полным решением, я собираюсь привести три разных способа сделать, но теперь я собираюсь начать с самого элементарного принципа.


Краткое введение

Все языки CLR ( Common Language Runtime ) (такие как C # и Visual Basic) работают под виртуальной машиной, называемой CLI ( Common Language Interpreter ), которая запускает код на более высоком уровне, чем родные языки, такие как C и C ++ (которые непосредственно компилируются для машинного кода) , Из этого следует, что методы не являются каким-либо скомпилированным блоком, но они представляют собой только структурированные элементы, которые CLR распознают и используют для вытягивания своего тела и привязывают его к встроенным инструкциям машинного кода. Таким образом, вы не можете думать, чтобы передать метод в качестве параметра, потому что метод не дает никакого значения сам по себе: это не допустимое выражение! Таким образом, вы собираетесь споткнуться о концепции делегата.


Что такое делегат?

Делегат представляет собой указатель на метод. Из-за (как я сказал выше) метод не является значением, на языках CLR есть специальный class: Delegate . Этот class обертывает любой метод, и вы можете косвенно использовать любой метод для этого.

Посмотрите следующий пример использования:

 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
    Используйте специальный class Delegate непосредственно в качестве примера выше. Проблема этого решения заключается в том, что ваш код будет отключен, поскольку вы динамически передаете свои аргументы, не ограничивая их типами в объявлении метода.

  • Путь 2/3 Помимо специального classа делегата, концепция делегатов распространяется на пользовательские delegates, которые являются декларациями методов, предшествующих ключевому слову 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"); } 

Второй вариант, чтобы не писать собственный пользовательский делегат, использует один из них, объявленный в системных библиотеках:

  • Action завершает void без аргументов.
  • Action обертывает void одним аргументом.
  • Action обертывает void двумя аргументами.
  • И так далее…
  • Func

    обертывает функцию с типом возврата TR и без аргументов.

  • Func обертывает функцию с типом возврата TR и одним аргументом.
  • Func обертывает функцию с типом возврата TR и двумя аргументами.
  • И так далее…

(Это последнее решение состоит в том, что многие люди разместили.)

Ниже приведен пример без параметра: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string

с параметрами: http://www.daniweb.com/forums/thread98148.html#

вы в основном передаете массив объектов вместе с именем метода. вы затем используете оба метода Invoke.

params Объект [] параметры

  • Что именно делает делегат в проекте xcode ios?
  • Является ли функция EndInvoke () опциональной, необязательной или необязательной?
  • Компилятор Неопределенная ошибка вызова - анонимный метод и группа методов с Func или действием
  • Что такое Func, как и когда он используется
  • Каковы различия между делегатами и событиями?
  • Разница между Invoke и DynamicInvoke
  • Как я могу совместно использовать объект между UIViewControllers на iPhone?
  • Выполнение вызовов делегатов против методов
  • Когда вы будете использовать делегатов в C #?
  • Подписка на динамические события C #
  • Как я могу очистить подписки на события в C #?
  • Interesting Posts

    Неверный class или магия файла

    Исправить SD-карту, которая не может быть отформатирована

    Каким образом исключения C ++ замедляют работу кода, если нет исключений?

    Почему C ++ не использует std :: nested_exception, чтобы позволить метать из деструктора?

    Информация о _JAVA_OPTIONS

    Преобразование NTFS в FAT32 без потери данных

    Есть ли способ получить ссылочный адрес?

    Процесс bash использует 90% процессор, возвращается на перезагрузку компьютера

    Как отправить данные из одного fragmentа в другой fragment?

    CORS: нельзя использовать подстановочный знак в Access-Control-Allow-Origin, когда флаг учетных данных верен

    Как отсортировать ArrayList, используя несколько критериев сортировки?

    Преобразование разделенных запятыми значений в несколько строк

    Рабочий стол Karmic Koala показывает только обои, ничего больше

    Как получить имена параметров метода в Java 8 с использованием отражения?

    Можно ли увеличить громкость звука Windows до более высокой ограниченной стоимости?

    Давайте будем гением компьютера.