簡體   English   中英

如何在C#中將函數作為參數傳遞?

[英]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);
        }

請看這里使用代表是一個很好的例子

代表示例

你為什么用反射? 會不會有不同數量的參數? 或者你知道方法signture將保持不變(還記得C#支持params []關鍵字)

params c#

HTH

骨頭

看看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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM