0

何に話したいかに応じて異なるメソッドを実行する必要があるプログラムがあり、ある種のメソッドポインタまたはそのようなものを配列に格納する方法があるかどうかを知りたいです。したがって、各要素が次のような配列になるようにします。

[ブール値:Do_this?][Function_pointer][関数に渡すデータ]

したがって、基本的には、これをforループに入れて、各関数を個別に呼び出すことはできません。別のコードブロックは、この関数を実行するかどうかのブール値を入力します。ブール値がtrueの場合、forループが実行され、適切なデータを使用して関数が実行されます。

デリゲートが関数ポインタに似ていることは知っていますが、それがここでの答えである場合、構築したいものをどのように構築するかは完全にはわかりません。

これはC#で可能ですか?

4

5 に答える 5

3

確かに、このようにするには、すべてのメソッドが同じシグネチャを持つ必要があります。

2つの方法があったとしましょう:

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

を作成するだけList<Action>です。アクションは、パラメーターを受け取らず、結果を返さないデリゲートです。カリー化とラムダを使用して、実際のアクションがパラメーターを持つメソッドを呼び出すことができるようにすることができます。実際に実行したくない場合は、そもそもリストに追加しないでください(または、私が推測することを何もしないアクションを追加してください)。

アイテムを追加するには、次のようになります。

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

次に、必要なときにすべてのアクションを実行できます。

foreach(Action action in list)
{
  action();
}
于 2012-07-11T17:12:17.187 に答える
1

はい、できます。

すべての関数が同じシグネチャを共有している場合は、デリゲートをコレクションに格納することをお勧めします。そうでない場合は、メソッドSystem.Reflection.MethodInfoを呼び出して後で使用できる、を選択しますInvoke。パラメータはオブジェクトの配列として保存されます-それがInvoke期待されていることです。

リフレクションの使用が遅すぎる場合はReflection.Emit、実行時に動的メソッドを生成するために使用できます。

于 2012-07-11T17:10:26.657 に答える
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 に答える