1

button1_clickで、次々にメッセージボックスが表示されます。最初に30が表示され、2番目に200が表示されます。

public partial class Form1 : Form
{

    delegate void myMathFunction(int j, int q);

    void add(int x, int y) {MessageBox.Show((x + y).ToString());}

    void multiply(int x, int y){MessageBox.Show((x*y).ToString());}

    private void button1_Click(object sender, EventArgs e)
    {
        myMathFunction foo = new myMathFunction(add);
        foo+= new myMathFunction(multiply);

        foo.Invoke(10, 20);
    }

    public Form1() { InitializeComponent(); }
}

しかし、以下は200に直接当てはまりますが、両方のメソッドをデリゲートに割り当てました-何が追加されたのか、なぜ乗算を使用することを選択したのですか?

public partial class Form1 : Form
{

    delegate int myMathFunction(int j, int q);

    int add(int x, int y){return x + y;}

    int multiply(int x, int y) {return x * y;}

    private void button1_Click(object sender, EventArgs e)
    {
        myMathFunction foo = new myMathFunction(add);
        foo += new myMathFunction(multiply);

        MessageBox.Show(foo.Invoke(10, 20).ToString());
    }

    public Form1() { InitializeComponent(); }
}

デリゲートがmultiplyメソッドではなくaddメソッドを実行するように、2番目のコードサンプルを修正できますか?

4

2 に答える 2

2

デリゲートに複数の関数がアタッチされている場合、それぞれが順番に呼び出されます。デリゲートにvoid以外の戻り値がある場合、最後の関数の戻り値が返されます。

言語仕様、15.4デリゲート呼び出しは、次のように述べています。

デリゲート呼び出しに出力パラメーターまたは戻り値が含まれている場合、それらの最終値は、リスト内の最後のデリゲートの呼び出しから取得されます。

したがって、を呼び出すfoo.Invoke(10, 20)と、次のようになります。

  • まず、add(10, 20)30を返すと呼ばれます。
  • 次に、multiply(10, 20)が呼び出され、200が返され、その値が元の呼び出し元に返されます。

フォローアップの質問であなたは尋ねます

デリゲートがmultiplyメソッドではなくaddメソッドを実行するように、2番目のコードサンプルを修正できますか?

上で説明したように、addメソッドメソッドのmultiply両方が実行されます。最後に実行されたメソッドからの戻り値は、呼び出し元に返されるものです。したがって、呼び出しの結果の値addを返す場合は、デリゲートインスタンスに追加された最後のメソッドである必要があります。

于 2012-05-12T21:34:22.997 に答える
2

C#言語仕様(§22.3)から:

呼び出しリストに複数のエントリが含まれているデリゲートインスタンスの呼び出しは、呼び出しリスト内の各メソッドを順番に同期的に呼び出すことによって続行されます。いわゆる各メソッドには、デリゲートインスタンスに与えられたものと同じ引数のセットが渡されます。そのようなデリゲート呼び出しに参照パラメーター(§17.5.1.2)が含まれている場合、各メソッド呼び出しは同じ変数への参照で発生します。呼び出しリスト内の1つのメソッドによるその変数への変更は、呼び出しリストのさらに下のメソッドに表示されます。 デリゲート呼び出しに出力パラメーターまたは戻り値が含まれている場合、それらの最終値は、リスト内の最後のデリゲートの呼び出しから取得されます。そのようなデリゲートの呼び出しの処理中に例外が発生し、その例外が呼び出されたメソッド内でキャッチされない場合、例外キャッチ句の検索は、デリゲートを呼び出したメソッド、および呼び出しのさらに下のメソッドで続行されます。リストは呼び出されません。

于 2012-05-12T21:38:59.263 に答える