4

実行時に a にアタッチされたデリゲートを変更したいと思いBackgroundWorkerます。以下のようなものは機能しますか?

DoWorkEvenHandler dweh = new DoWorkEventHandler(method1);
backgroundworker.DoWork += dweh;

DoWorkそして、後で参照を再割り当てすることで、関連付けられているデリゲートを変更しdwehます。

dweh = new DoWorkEventHandler(method2);
4

2 に答える 2

8

いいえ、デリゲートをイベント ハンドラーに "割り当てる" ことはできません。ハンドラーは、イベントを表すために内部的に使用される基になるデリゲートの呼び出しリストにハンドラーを追加することによって、イベントにアタッチされます。これは設計によるものです。

いいえ、イベント ハンドラーをアタッチするために以前に使用された参照が指すオブジェクトを変更することによって、ハンドラーを変更することはできません。一部にはデリゲートが immutableであるため、また一部には参照を変更して別のものを指すようにするためであり、達成しようとしているイベントハンドラーを実際には変更しないためです。

デリゲートを変更するには、まず前のデリゲートを削除する必要があります。

backgroundworker.DoWork -= dweh;

次に、イベントのハンドラーとして追加して、新しいものを割り当てます。

backgroundworker.DoWork += new DoWorkEventHandler(method2);

ノート

ほとんどの場合、次の構文を使用して、イベントからハンドラー (デリゲート) を削除できます。

backgroundworker.DoWork -= new DoWorkEventHandler(mehtod1);

または、暗黙的または明示的なメソッド グループ変換を使用します。

backgroundworker.DoWork -= (DoWorkEventHandler)mehtod1;  // explicit convertion    
//  -  or  - 
backgroundworker.DoWork -= mehtod1;                      // implicit (more compact)

ただし、状況によっては、後で削除できるようにするために、前のデリゲートへの参照を維持する必要がある場合があります。たとえば、これは匿名メソッドまたはラムダ式に適用されます。

于 2013-03-04T20:32:11.260 に答える
0

これは、ことわざの「余分なレベルの間接参照」で解決できます。次のようなクラスを作成します。

public sealed class RedirectableDoWorkEventHandler
{
    public RedirectableDoWorkEventHandler(DoWorkEventHandler handler)
    {
        Contract.Requires(handler != null);
        _handler = handler;
    }

    public DoWorkEventHandler Handler
    {
        get
        {
            return _handler;
        }

        set
        {
            Contract.Requires(value != null);
            _handler = value;
        }
    }

    public void DoWork(object sender, DoWorkEventArgs e)
    {
        _handler(sender, e);
    }

    private DoWorkEventHandler _handler;
}

そして、次のように使用できます。

public void Setup()
{
    BackgroundWorker worker = new BackgroundWorker();

    // ...

    var handler = new RedirectableDoWorkEventHandler(handler1);

    worker.DoWork += handler.DoWork;

    // And then some time later...

    handler.Handler = handler2; // Now DoWork will call handler2.
}

private void handler1(object sender, DoWorkEventArgs e)
{
    // Whatever
}

private void handler2(object sender, DoWorkEventArgs e)
{
    // Whatever
}

しかし、本当に、ポイントは何ですか?if選択肢の中から選択するための単純なハンドラーが1つだけある場合もあります。場合によってはカプセル化するのに役立つと思います...YMMV。

于 2013-03-04T21:02:59.793 に答える