我有几种方法都具有相同的签名(参数和返回值),但是不同的名称和方法的内部原理不同。 我想将要运行的方法的名称传递给另一个方法,该方法将调用传入的方法。
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代码,因为我需要定义参数。
#1楼
这是一个示例,可以帮助您更好地理解如何将函数作为参数传递。
假设您具有“ 父”页面,并且想要打开一个子弹出窗口。 在父页面中,应基于子弹出文本框填充一个文本框。
在这里您需要创建一个委托。
Parent.cs //代表声明公共代表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构造函数中,您需要创建父级//页面的“代理类型”参数
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;
}
#2楼
您需要使用一个委托 。 在这种情况下,所有方法都使用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#,您可以通过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
方法。
您可以将委托用于事件订阅,异步执行,回调-各种各样的事情。 值得一读,特别是如果您想使用LINQ。 我有一个文章 ,其主要是关于委托和事件之间的差异,但你会发现它很有用呢。
1这只是基于框架中的泛型Func<T, TResult>
委托类型; 您可以轻松声明自己的:
public delegate int MyDelegateType(string value)
然后使参数的类型为MyDelegateType
。
#3楼
您应该使用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);
}
#4楼
这是一个不带参数的示例: 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 []参数
#5楼
如果您希望能够在运行时更改调用哪种方法,则建议使用委托: http : //www.codeproject.com/KB/cs/delegates_step1.aspx
它将允许您创建一个对象来存储要调用的方法,并且可以在需要时将其传递给其他方法。
#6楼
您可以将.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);
}
}
#7楼
public static T Runner<T>(Func<T> funcToRun)
{
//Do stuff before running function as normal
return funcToRun();
}
用法:
var ReturnValue = Runner(() => GetUser(99));
#8楼
虽然接受的答案是绝对正确的,但我想提供一种其他方法。
在我自己寻找类似问题的解决方案之后,我在这里结束了。 我正在构建一个插件驱动的框架,作为框架的一部分,我希望人们能够将应用程序菜单中的菜单项添加到通用列表,而无需暴露实际的Menu
对象,因为该框架可能会部署在没有此功能的其他平台上Menu
UI对象。 添加有关菜单的常规信息非常容易,但是事实证明,允许插件开发人员有足够的自由来创建单击菜单时的回调。 直到我意识到,我一直在尝试重新发明方向盘和普通菜单调用并触发事件回调!
因此,解决方案(听起来很简单)一到您就意识到了。
只需为每个当前方法创建单独的类(如果需要,可以从基类继承),然后向每个方法添加事件处理程序。
#9楼
为了共享尽可能完整的解决方案,我将以三种不同的操作方式结束,但是现在,我将从最基本的原则开始。
简单的介绍
所有CLR( 公共语言运行时 )语言(例如C#和Visual Basic)都在称为CLI( 公共语言解释器 )的VM下工作,该VM在比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<T1, TR>
包装了一个具有TR
返回类型和一个参数的函数。 -
Func<T1, T2, TR>
包装了一个具有TR
返回类型和两个参数的函数。 - 等等...
(后一种解决方案是大多数人发布的解决方案。)
#10楼
如果要将方法作为参数传递,请使用:
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");
}
#11楼
class PersonDB
{
string[] list = { "John", "Sam", "Dave" };
public void Process(ProcessPersonDelegate f)
{
foreach(string s in list) f(s);
}
}
第二类是客户端,它将使用存储类。 它具有Main方法,该方法创建PersonDB的实例,并使用Client类中定义的方法调用该对象的Process方法。
class Client
{
static void Main()
{
PersonDB p = new PersonDB();
p.Process(PrintName);
}
static void PrintName(string name)
{
System.Console.WriteLine(name);
}
}
#12楼
从OP的示例:
public static int Method1(string mystring)
{
return 1;
}
public static int Method2(string mystring)
{
return 2;
}
您可以尝试动作代表! 然后使用
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"));