0

我有一个程序需要根据我希望它与之交谈的内容运行不同的方法,并且我想知道是否有一种方法可以将某种方法指针或类似的东西存储在数组中。所以我想要一个数组,其中每个元素都是这样的:

[布尔值:Do_this?] [Function_pointer] [传递给函数的数据]

所以基本上,我可以把它放到一个 for 循环中,而不是单独调用每个函数。另一个代码块将填写是否运行此函数的布尔值,然后如果布尔值为真,我的 for 循环将通过并使用其适当的数据运行该函数。

我知道委托类似于函数指针,但如果这是这里的答案,我不完全确定我将如何构造我想要构造的东西。

这在 C# 中可能吗?

4

5 回答 5

3

当然,虽然要这样做,但您需要所有方法都具有相同的签名:

假设您有两种方法:

public int Moop(string s){ return 1; }
public int Moop2(string s){ return 2; }

你可以这样做:

var funcs = new Func<string, int>[]{ Moop, Moop2 };

并致电:

var val = funcs[0]("hello");
于 2012-07-11T17:10:53.493 回答
2

您可以声明要保存在委托中的特定对象类型、指示是否执行此操作或现在执行此操作的标志以及数据。请注意,您所描述的内容与事件非常相似,因为它们也是由回调和一些事件数据定义的。

骨架模型看起来像这样,假设您要调用的所有方法都具有相同的签名(如果您需要使用反射来获得一大堆不同的签名,您可以解决这个问题):

// This reflects the signature of the methods you want to call
delegate void theFunction(ActionData data);

class ActionData
{
    // put whatever data you would want to pass
    // to the functions in this wrapper
}

class Action
{
    public Action(theFunction action, ActionData data, bool doIt)
    {
        this.action = action;
        this.data = data;
        this.doIt = doIt;
    }

    public bool doIt
    {
        get;
        set;
    }

    public ActionData data
    {
        get;
        set;
    }

    public theFunction action
    {
        get;
        set;
    }

    public void run()
    {
        if (doIt)
            action(data);
    }
}

一个常规的用例看起来像这样:

class Program
{
    static void someMethod(ActionData data)
    {
        Console.WriteLine("SUP");
    }

    static void Main(string[] args)
    {
        Action[] actions = new Action[] {
            new Action(Program.someMethod, new ActionData(), true)
        };

        foreach(Action a in actions) 
            a.run();
    }
}
于 2012-07-11T17:19:11.893 回答
1

是的你可以。

如果您的所有函数共享相同的签名,您可能希望将委托存储在您的集合中,否则我会选择System.Reflection.MethodInfo,您可以稍后通过调用Invoke方法来使用它。参数将存储为对象数组 - 这是Invoke预期的。

如果使用反射太慢,您可以使用Reflection.Emit在运行时生成动态方法。

于 2012-07-11T17:10:26.657 回答
1

我只会创建一个List<Action>. Action 是一个不带参数且不返回结果的委托。您可以使用 currying 和 lambda,以便实际操作可以调用具有参数的方法。如果您实际上不想运行它,请首先不要将其添加到列表中(或者添加一个我猜什么都不做的操作)。

要添加一个项目,它可能看起来像:

list.Add(() => someobject.someMethod(firstArgument, secondArgument));
list.Add(() => anotherObject.anotherMethod(oneArgument));

然后,您可以在需要时运行所有操作:

foreach(Action action in list)
{
  action();
}
于 2012-07-11T17:12:17.187 回答
0

这正是您使用委托的目的。委托或多或少是经过类型检查的函数指针。您可以创建一些委托并将它们放入一个数组中。

Func<int, int> [] funcs = new Func<int,int>[] { x => 2 * x, x => x * x };
foreach(var fn in funcs) 
{
    Console.WriteLine(fn(3));
    Console.WriteLine(fn(8));
}
于 2012-07-11T17:10:41.840 回答