У меня есть несколько методов с одной и той же сигнатурой (параметры и возвращаемые значения), но разные имена и внутренние методы отличаются. Я хочу передать имя метода для запуска другому методу, который вызовет переданный метод.
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 позволяет вам указать метод, который принимает ряд параметров определенного типа и возвращает один аргумент определенного типа. Вот пример, который должен работать:
источник
Action
вместоFunc<string, int>
.Action<int,string>
соответствует методу, который принимает 2 параметра (int и string) и возвращает void.Func<double,string,int>
соответствует методу, который принимает 2 параметра (double
иstring
) и возвращаетint
. Последний указанный тип является типом возвращаемого значения. Вы можете использовать этот делегат для 16 параметров. Если вам как-то нужно больше, напишите свой собственный делегат какpublic delegate TResult Func<in T1, in T2, (as many arguments as you want), in Tn, out TResult>(T1 arg1, T2 arg2, ..., Tn argn);
. Пожалуйста, поправьте меня, если я неправильно понял.Вам нужно использовать делегата . В этом случае все ваши методы принимают
string
параметр и возвращаютint
- это наиболее просто представленоFunc<string, int>
делегатом 1 . Таким образом, ваш код может стать правильным с таким простым изменением, как это:По общему признанию, делегаты обладают гораздо большей властью, чем эта. Например, в C # вы можете создать делегат из лямбда-выражения , чтобы вы могли вызывать свой метод следующим образом:
Это создаст анонимную функцию, подобную этой:
а затем передать этот делегат в
RunTheMethod
метод.Вы можете использовать делегатов для подписки на события, асинхронного выполнения, обратных вызовов - все виды вещей. Об этом стоит прочитать, особенно если вы хотите использовать LINQ. У меня есть статья, которая в основном посвящена различиям между делегатами и событиями, но в любом случае вы можете найти ее полезной.
1 Это просто основано на универсальном
Func<T, TResult>
типе делегата в структуре; Вы можете легко заявить о себе:а затем
MyDelegateType
вместо этого сделайте параметр типа .источник
public **delegate** int MyDelegateType(string value)
?Из примера OP:
Вы можете попробовать Action Delegate! А затем вызвать ваш метод с помощью
Или
Тогда просто вызовите метод
источник
InvokeMethod
лямбда-звонок должен бытьRunTheMethod
вместо этогоПрименение:
источник
Для того, чтобы поделиться как можно более полным решением, я собираюсь представить три различных способа работы, но теперь я собираюсь начать с самого основного принципа.
Краткое введение
Все языки, которые работают поверх CLR ( Common Language Runtime ), такие как C #, F # и Visual Basic, работают под виртуальной машиной, которая выполняет код на более высоком уровне, чем родные языки, такие как C и C ++ (которые непосредственно компилируются в машину). код). Из этого следует, что методы - это не какой-либо вид скомпилированного блока, а просто структурированные элементы, которые распознает CLR. Таким образом, вы не можете думать о том, чтобы передать метод в качестве параметра, потому что методы сами не производят никаких значений, так как они не являются выражениями! Скорее, это операторы, которые определены в сгенерированном коде CIL. Итак, вы столкнетесь с концепцией делегата.
Кто такой делегат?
Делегат представляет указатель на метод. Как я уже говорил выше, метод не является значением, поэтому в языках CLR есть специальный класс
Delegate
, который заключает в себе любой метод.Посмотрите на следующий пример:
Три разных способа, одна и та же концепция:
Способ 1
Используйте
Delegate
специальный класс напрямую, как в примере выше. Проблема этого решения заключается в том, что ваш код не будет проверяться при динамической передаче аргументов, не ограничивая их типами, указанными в определении метода.Способ 2
Помимо
Delegate
специального класса, концепция делегата распространяется на пользовательские делегаты, которые являются определениями методов, которым предшествуетdelegate
ключевое слово, и ведут себя так же, как обычные методы. Тем самым они проверяются, поэтому вы получите безупречно безопасный код.Вот пример:
Способ 3 В
качестве альтернативы, вы можете использовать делегата, который уже был определен в .NET Standard:
Action
оборачиваетvoid
без аргументов.Action<T1>
оборачиваетvoid
с одним аргументом.Action<T1, T2>
оборачиваетvoid
с двумя аргументами.Func<TR>
оборачивает функцию сTR
типом возврата и без аргументов.Func<T1, TR>
оборачивает функцию сTR
типом возврата и с одним аргументом.Func<T1, T2, TR>
оборачивает функциюTR
возвращаемым типом и двумя аргументами.(Последнее решение - то, которое большинство людей отправило.)
источник
Func<T1,T2,TR>
Вы должны использовать
Func<string, int>
делегат, который представляет функцию, принимающую вstring
качестве аргумента и возвращающуюint
:Тогда используйте это:
источник
Test
Метод должен бытьreturn RunTheMethod(Method1);
Если вы хотите изменить способ вызова метода во время выполнения, я бы порекомендовал использовать делегата: http://www.codeproject.com/KB/cs/delegates_step1.aspx.
Это позволит вам создать объект для хранения вызываемого метода, и вы можете передать его другим методам, когда это необходимо.
источник
Хотя принятый ответ является абсолютно правильным, я хотел бы предоставить дополнительный метод.
Я попал сюда после того, как сам занялся поиском решения аналогичного вопроса. Я создаю платформу, управляемую плагином, и как часть этого я хотел, чтобы люди могли добавлять пункты меню в меню приложений в общий список, не раскрывая фактический
Menu
объект, потому что платформа может развертываться на других платформах, которые не имеютMenu
пользовательского интерфейса объекты. Добавление общей информации о меню достаточно просто, но предоставление разработчику плагина достаточной свободы для создания обратного вызова, когда при щелчке по меню оказывалось трудным делом. Пока меня не осенило, что я пытался заново изобрести колесо и обычное меню вызова и вызвать обратный вызов от событий!Таким образом, решение, настолько простое, насколько это звучит, когда вы его осознаете, ускользало от меня до сих пор.
Просто создайте отдельные классы для каждого из ваших текущих методов, унаследованных от базы, если необходимо, и просто добавьте обработчик событий для каждого из них.
источник
Вот пример, который может помочь вам лучше понять, как передать функцию в качестве параметра.
Предположим, у вас есть родительская страница, и вы хотите открыть дочернее всплывающее окно. На родительской странице есть текстовое поле, которое должно быть заполнено на основе дочернего всплывающего текстового поля.
Здесь вам нужно создать делегата.
Parent.cs // объявление делегатов публичный делегат void FillName (String FirstName);
Теперь создайте функцию, которая заполнит ваше текстовое поле, и функция должна отображать делегатов.
Теперь при нажатии кнопки вам нужно открыть всплывающее окно Child.
В конструкторе ChildPopUp необходимо создать параметр «тип делегата» родительской // страницы
ChildPopUp.cs
источник
Если вы хотите передать метод в качестве параметра, используйте:
источник
Вот пример без параметра: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
с параметрами: http://www.daniweb.com/forums/thread98148.html#
вы в основном передаете массив объектов вместе с именем метода. Затем вы используете оба метода Invoke.
params Object [] параметры
источник
Второй класс - это Клиент, который будет использовать класс хранения. У него есть метод Main, который создает экземпляр PersonDB, и он вызывает метод Process этого объекта с методом, который определен в классе Client.
источник