10

C# 中是否有任何方法可以保存函数调用以供以后调用?例如,我想能够说:

public class MyFunctionCaller
{
    public static void SaveFunctionCallForLater(/* Some parameters*/)
    {
    // Save the Function Call in a variable or a list to be invoked after a set amount of time
   }
}

public class MyProgram
{
    public static void Main()
    {
        // Save a call to 'SpecialFunction' along with its parameters,
        // and maybe the object that's calling it (not applicable in
       // this example context, but important to my question)
        MyFunctionCaller.SaveFunctionCallForLater(/* Stuff */);
    }

    public void SpecialFunction(/* Stuff */)
    {
        // Does some cool stuff
    }
}

让我给你一些背景信息:我正在 XNA 中创建一个游戏,我想创建一个 DelayedFunctionCaller 类,任何对象都可以引用它来手动完成函数调用,以及在调用函数之前等待的时间。我自己处理所有的时间等待和触发,所以这不是我迷路的地方,我只是不确定如何或正确的方法来打包要传递给 DelayedFunctionCaller 的函数。

这是踢球者:DelayedFunctionCaller 必须能够运行任何函数,无论是什么对象向它发送函数,函数返回什么,或者它需要什么参数**。我的游戏中已经有 100 多个类,目标是创建一个对象,该对象可以保存其中任何一个的任何函数调用以供以后调用。

所以从我自己的研究中,我找到了Typeclass,并且我知道我可以将对象调用的类型、函数名保存为字符串(这是可以接受的牺牲),然后用于GetMethod()将方法保存在 a 中MemberInfo,然后使用MemberInfo'sInvoke()调用函数,即使是在保存的对象上,并使用参数(作为 的数组Objects)。

但这一切似乎都非常... hack-ish。我曾尝试查找此内容,并认为Generic Delegates是我想走的路,但我迷失在那里,我放弃了。我在正确的轨道上吗?这是唯一的方法吗?Generic Delegates 呢,或者当我认为它可以解决我的问题时,我只是在发疯?

任何和所有的帮助表示赞赏。谢谢!

4

2 回答 2

22

您可以使用lambda 表达式将其保存为操作:

Action functionToCallLater = () => SpecialFunction(/* params */);
// later
functionToCallLater(); // calls SpecialFunction with its parameters

如果函数返回一些东西并且你需要它的值,只需使用Func<T>类型来代替。

int MyMethod(int param) { return param + 1; }
(...)
Func<int> functionToCallLater = () => MyMethod(3);
(...)
int result = functionToCallLater(); // result == 4

请记住,您在 lambda 中使用的任何变量都是自己捕获的,而不是它的值;如果它的值发生变化,那将是调用函数时使用的值。有关更深入的解释,请参阅Eric Lippert的博客。

于 2012-06-03T03:13:56.363 回答
0

除了 lambda 表达式,您还可以使用IEnumerableorIEnumerable<T>方法。之后,调用方法使用 foreach 指令。例如,这个 Unity 引擎代码:

using UnityEngine;
using System.Collections;

public class temp : MonoBehaviour {

    public IEnumerable myMethod1(string str){

        Debug.Log(str);
        yield return null;

    }

    public IEnumerable myMethod2(int number, string str){

        Debug.Log(number+str);
        yield return null;

    }

    System.Action CreateAction(params IEnumerable[] methodsArray){

        return () =>{

            IEnumerable[] methods = methodsArray;
            foreach(IEnumerable method in methods){ foreach(IEnumerable run in method); };

        };

    }


    void Start(){

        System.Action methodGroup = CreateAction(myMethod1("one"),myMethod2(1234,"two"));
        methodGroup();

    }
}
于 2014-10-28T08:56:45.790 回答