[英]How to pass a function as a parameter in C#?
是否可以在C#中将函数作为参数传递? 我可以使用Func或Action类来完成它,但这迫使我立刻声明整个函数签名。 当我尝试使用Delegate时,我收到一个编译错误,说它无法将方法组转换为Delegate。
我正在研究Axial ,我正试图让用户调用Web服务。 我想要的是能够创建Visual Studio代理类,然后传入生成的函数。 函数签名无关紧要,因为生成的代码仅使用函数名称。 但是,我想传递函数而不是名称有两个原因:如果Web服务不存在或在Visual Studio中更新,则能够使用代理的Url属性和编译器错误。
public void AlertIt(object o) {
Axial.DOM.Window.Alert(o.ToString());
}
public void CallAddService() {
object[] param = new object[] { int.Parse(txtA.Text), int.Parse(txtB.Text) };
Axial.ServerScript.CallWebService(new WSProxy.WS().Add, param, AlertIt, AlertIt);
}
class Axial.ServerScript {
public void CallWebService(Delegate method, object[] param, Action<object> successCallback, Action<object> failureCallback) {
// translate to javascript (already working)
}
}
我想你想要的是:
static object InvokeMethod(Delegate method, params object[] args){
return method.DynamicInvoke(args);
}
static int Add(int a, int b){
return a + b;
}
static void Test(){
Console.WriteLine(InvokeMethod(new Func<int, int, int>(Add), 5, 4));
}
打印“9”。
将方法组,匿名方法或lambda表达式转换为委托要求编译器知道确切的委托类型。 但是,您可以使用lambda表达式和捕获的变量来使这更简单:
public void InvokeMethod(Action action)
{
action();
}
public int Add(int a, int b)
{
return a + b;
}
public void Test()
{
InvokeMethod(() => Add(2, 3));
}
这基本上会以正常方式延迟调用,但是通过在普通的Action
委托中包含实际调用Add
。
如果这不符合您的要求,也许您可以告诉我们更多关于您真正想要达到的目标。
编辑:如果这是生成的代码,你可以使用正确的类型参数Func<...>
转换为Func<...>
- 假设没有太多。 除此之外,没有真正的方法只是传递方法组。 偶尔需要一个“infoof(...)”运算符(比如typeof但对于成员来说)会给你一个MemberInfo,但实际上并不存在。
你应该先有一个代表
delegate int Operation(int a, int b)
然后它变成:
public void InvokeMethod(Operation method, object target, object param)
{
method((int) target, (int) param);
}
无需调用Invoke。
与dbone一样,我不确定为什么你需要一个params []数组。 你会澄清params的扩展用法吗?
此外,我将不得不纠正你的问题,因为它会导致编译错误:p
这是一个非常简单的例子,对于已经熟悉( C / C ++ / VB.NET/Python )风格的程序员来说,通过pointer / ref (使用C#委托 )传递函数:
delegate void CALLBACK(String s);
static void Main(string[] args)
{
Get("some string", testfunc);
Util.pause();
}
static void Get(String s, CALLBACK x)
{
x(s);
}
static void testfunc(String s)
{
Console.WriteLine(s);
}
看看Justin Etheredge的功能编程系列 。 您应该在那里找到解决问题的方法。
说如果您需要将方法作为参数传递,则需要捕获返回值以进行进一步处理。 那么上面的例子就可以了。 但是如果你需要传递一个带有void返回类型的方法,那么你需要再创建一个InvokeMethod函数版本。 请查看以下示例。
private static T retry<T>(Delegate method, params object[] args)
{
for (int i = 0; i <= 3; i++)
{
try
{
return (T)method.DynamicInvoke(args);
}
catch (Exception ex)
{
if (i == 3)
{
logMessage(ex.Message);
}
Console.WriteLine("Retry count " + i);
Thread.Sleep(10);
}
}
return default(T);
}
private static void retry2(Delegate method, params object[] args)
{
for (int i = 0; i <= 3; i++)
{
try
{
method.DynamicInvoke(args);
break;
}
catch (Exception ex)
{
if (i == 3)
{
logMessage(ex.Message);
//return default(T);
}
Console.WriteLine("Retry count " + i);
Thread.Sleep(10);
}
}
}
static bool isSuccess = true;
static void logMessage(string msg)
{
isSuccess = false;
Console.WriteLine(msg);
}
static int Add(int a, int b)
{
return a + b;
}
static void Add2(int a, int b)
{
int c = a + b;
Console.WriteLine(c);
}
static void Main(string[] args)
{
int d = retry<int>(new Func<int, int, int>(Add), 6, 7.7);
Console.Write(" " + d + "\n"+isSuccess);
retry2(new Action<int, int>(Add2), 45, 60);
Console.ReadKey();
}
这样的事情应该适合你:
delegate int MyDelegate(int a, int b);
public int Add(int a, int b) {
return a + b;
}
public void InvokeMethod(Delegate method, object[] param) {
Console.WriteLine(method.DynamicInvoke(param));
}
public Form1() {
InitializeComponent();
InvokeMethod(new MyDelegate(Add), new object[] { 1, 2 });
}
祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.