Метод Pass в качестве параметра с использованием 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, так как мне нужно определить параметр.
10 ответов
вы можете использовать делегат 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<string, int> myMethodName)
{
//... do stuff
int i = myMethodName("My String");
//... do more stuff
return true;
}
public bool Test()
{
return RunTheMethod(Method1);
}
}
вы также можете попробовать делегат action!
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<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);
}
Если вы хотите иметь возможность изменять, какой метод вызывается во время выполнения, я бы рекомендовал использовать делегат:http://www.codeproject.com/KB/cs/delegates_step1.aspx
Это позволит вам создать объект для хранения метода для вызова, и вы можете передать его другим методам, когда это необходимо.
хотя принятый ответ абсолютно правильный, я хотел бы предоставить дополнительный метод.
я оказался здесь после того, как сделал свой собственный поиск решения аналогичного вопроса.
Я создаю структуру, управляемую плагином, и в рамках этого я хотел, чтобы люди могли добавлять пункты меню в меню приложений в общий список, не подвергая фактическому Menu
объект, потому что платформа может развертываться на других платформах, которые не имеют Menu
объекты пользовательского интерфейса. Добавление общего информация о меню достаточно проста, но позволяя разработчику плагина достаточно свободы для создания обратного вызова при нажатии на меню оказалось болью. Пока до меня не дошло, что я пытаюсь заново изобрести колесо и обычное меню вызова и вызвать обратный вызов из событий!
просто создайте отдельные классы для каждого из ваших текущих методов, унаследованных от базы, если вы must, и просто добавьте обработчик событий к каждому.
для обмена как можно более полным решением, я собираюсь в конечном итоге представить три разных способа сделать, но теперь я собираюсь начать с самого основного принципа.
краткое введение
все CLR (Среда CLR) языки (такие как C# и Visual Basic) работают под виртуальной машиной с именем CLI (Переводчик Общего Языка), который запускает код на более высоком уровне, чем родные языки, такие как C и c++ (которые непосредственно компилируются в машинный код). Из этого следует, что методы не являются каким-либо скомпилированным блоком, но они просто структурированные элементы, которые 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
специальный класс непосредственно в качестве примера выше. Проблема этого решения заключается в том, что ваш код будет снят при динамической передаче аргументов, не ограничивая их типами в объявлении метода.способ 2/3 Кроме
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");
}
второй вариант таким образом, чтобы не писать свой собственный делегат, использует один из них, объявленный в системных библиотеках:
-
Action
обертываетvoid
без аргументов. -
Action<T1>
обертываетvoid
С одним аргументом. -
Action<T1, T2>
обертываетvoid
С двумя аргументами. - и так на...
-
Func<TR>
обертывает функцию сTR
возвращаемый тип и без аргументов. -
Func<TR, T1>
обертывает функцию с помощьюTR
возвращаемый тип и с одним аргументом. -
Func<TR, T1, T2>
обертывает функцию сTR
возвращаемый тип и с двумя аргументами. - и так далее...
(последнее решение заключается в том, что многие люди в курсе.)
вот пример, который может помочь вам лучше понять, как передать функцию в качестве параметра.
Предположим, у вас есть родитель страница, и вы хотите открыть дочернее всплывающее окно. На родительской странице есть текстовое поле, которое должно быть заполнено на основе дочернего всплывающего текстового поля.
здесь вам нужно создать делегата.
родитель.цезий // заявление делегатов public delegate void FillName (String FirstName);
Теперь создайте функцию, которая заполнит ваше текстовое поле, и функция должна отобразить делегатов
//parameters
public void Getname(String ThisName)
{
txtname.Text=ThisName;
}
Теперь при нажатии кнопки вам нужно открыть всплывающее окно ребенка.
private void button1_Click(object sender, RoutedEventArgs e)
{
ChildPopUp p = new ChildPopUp (Getname) //pass function name in its constructor
p.Show();
}
в конструкторе ChildPopUp вам нужно создать параметр "тип делегата" родительского / / 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;
}
вот пример без параметра: http://en.csharp-online.net/CSharp_FAQ:_How_call_a_method_using_a_name_string
с params: http://www.daniweb.com/forums/thread98148.html#
вы в основном передаете массив объектов вместе с именем метода. затем вы используете оба метода вызова.
параметр params объекта[] параметры