【问题标题】:C# How to save a function-call for in memory for later invokingC#如何将函数调用保存在内存中以供以后调用
【发布时间】:2012-06-03 03:02:28
【问题描述】:

在 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 多个类,目标是创建一个对象,可以保存其中任何一个的任何函数调用以供以后调用。

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

但这一切看起来都非常... hack-ish。我试着查了一下,认为Generic Delegates 是我想走的路,但我在那里迷失了方向,所以我放弃了。我在正确的轨道上吗?这是唯一的方法吗? Generic Delegates 呢,或者当我认为它可以解决我的问题时,我只是疯了?

感谢任何和所有帮助。谢谢!

【问题讨论】:

  • 您是否正在寻找类似this 的东西,除了它适用于具有任意数量参数等的任何方法?

标签: c# types delegates xna


【解决方案1】:

您可以将其保存为操作,使用 lambda expression:

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 的博客以获得更深入的解释。

【讨论】:

  • ...嗯,这是我不知道的事情。从我可以查看 atm 的所有内容中,我一直在阅读 Actions 永远不能有超过 2 个变量,而且我从未见过其他示例。我真的可以调用“Action savedAction = () => SpecialFunction(param1, param2, param3);”吗?另外,我没有在 lamdba 调用的“()”部分中添加任何参数,对吗?
  • Action 对象本身不需要参数;参数保存在 lambda 表达式中。这就是你想要的,对吧?您希望将函数调用及其参数保存在稍后可以调用的内容中,这正是我的示例所做的。阅读我在 MSDN 上链接到的页面,这应该会为您解决问题。
  • 我可以补充一下,如果您希望将变量的确切当前值发送到方法,您应该在创建 Action 之前将它们复制到 tmp 变量,而不是更改 tmp变量直到作用域结束。
  • 完美,Dr_Asik,这正是我想要的,只是确保 =)
  • 值得注意的是,特别是对于我们这些在 XNA 中工作的人来说,lambda 表达式会产生很多垃圾。每个 () => 表达式相当于调用new Action,这当然是在堆上放置一个对象;此外,具有封闭外部变量的 lambda 表达式被编译器提升为隐藏类,并且该类被实例化和调用的方式意味着每次调用委托时都会产生额外的垃圾。如果性能受到关注,请谨慎使用它们。
【解决方案2】:

除了 lambda 表达式,您还可以使用 IEnumerableIEnumerable&lt;T&gt; 方法。之后,调用方法使用 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();

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 2019-06-15
    • 2021-10-06
    • 1970-01-01
    相关资源
    最近更新 更多