2

カスタム イベント引数クラスが から直接継承しているのに、イベントをサブスクライブするメソッドにカスタム イベント引数を直接渡すことができないのはなぜEventArgsですか?

たとえば、以下の 2 つのクラスを考えてみましょう。1 つは使用したいクラスで、もう 1 つは から継承されEventArgs、イベントに関連する追加情報が含まれています。

using System;

namespace ConsoleApplication11
{
    class MyClass
    {
        public event EventHandler MyEvent;

        public void MyMethod(int myNumber)
        {
            Console.WriteLine(myNumber);

            if(myNumber == 7)
            {
                MyEvent.Invoke(null, new MyCustomEvent() { Foo = "Bar" });
            }
        }
    }

    class MyCustomEvent : EventArgs
    {
        public string Foo { get; set; }
    }
}

したがって、数値 7 が に渡された場合、クラスの新しいインスタンスを、イベントをサブスクライブする任意のメソッドに渡すMyMethodことを呼び出したいと思います。MyEventMyCustomEvent

私はメインプログラムからこれを次のようにサブスクライブします:

using System;

namespace ConsoleApplication11
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
            myClass.MyEvent += new EventHandler(myClass_MyEvent);

            for (int i = 0; i < 9; i++)
            {
                myClass.MyMethod(i);
            }
        }

        static void myClass_MyEvent(object sender, EventArgs e)
        {
            //Do Stuff
        }
    }
}

イベントを呼び出すときにオブジェクトを渡していMyCustomEventますが、イベントをサブスクライブするメソッドの 2 番目のパラメーターをオブジェクトに変更するとMyCustomEvent、コンパイル エラーが発生します。代わりに、クラス内の追加のフィールド/メソッドなどにアクセスEventArgsする前に、オブジェクトを明示的にキャストする必要があります。MyCustomEvent

多数の異なるイベントを持つオブジェクトを操作する場合、それぞれのイベントに固有の関連するカスタムEventArgsクラスがあり、各イベントをサブスクライブする各メソッドの EventArgs を何にキャストする必要があるかを追跡するのは少し面倒です。

カスタム EventArgs クラスを、イベントをサブスクライブするメソッドに直接渡すことができれば、はるかに簡単になります。

これは可能性がありますか?

ありがとう

4

5 に答える 5

5

イベントを type として宣言する代わりにEventHandler、カスタム イベント引数クラスを具体的に使用する新しいデリゲートを作成します。

public delegate void MyEventHandler(object sender, MyEventArgs args);
public event MyEventHandler MyEvent;

これで、キャストせずに引数を直接渡すことができます。

他のオプションは、ジェネリックを使用することEventHandler<T>です:

public event EventHandler<MyEventArgs> MyEvent;

デリゲート型によりわかりやすい名前を付けることができるため、私は前者を好みますが、後者の方が少し迅速です。

于 2012-07-16T17:05:03.153 に答える
1

私があなたの質問を間違って理解したなら、私を許してください。EventArgsカスタムクラスが表示されないので少し混乱しています。

次のようなメソッドシグネチャを作成することはできません

static void myClass_MyEvent(object sender, CustomEventArgs e)

を期待するイベントの場合

static void myClass_MyEvent(object sender, EventArgs e)

これは後方ポリモーフィズムであり、ポリモーフィズムは後方に機能しません。

イベントがにアクセスしますe.OnlyInCustomEventArgsが、代わりにベースオブジェクトが渡されたとしますEventArgs。その後、契約は破られました。

今あなたができることは

static void myClass_MyEvent(object sender, EventArgs e)
{
    CustomEventArgs cea = (CustomEventArgs)e;
}
于 2012-07-16T17:06:25.697 に答える
1

デフォルトのイベントハンドラーを使用するのではなく、達成しようとしている署名に合った独自のイベントハンドラーを定義するだけです...

public delegate void MyEventHandler(object sender, MyCustomEventArgs e)
public event MyEventHandler MyEvent;
于 2012-07-16T17:04:40.267 に答える
1

の汎用バージョンを使用してイベントを宣言しますEventHandler

public event EventHandler<MyCustomEvent> MyEvent;
于 2012-07-16T17:03:51.470 に答える
0

以下は、正しく実装されたカスタム arg イベント ハンドラの完全なコードです。

class MyClass
{
    public event EventHandler<MyCustomEventArgs> MyEvent;

    public void MyMethod(int myNumber)
    {
        Console.WriteLine(myNumber);

        if (myNumber == 7)
        {
            MyEvent.Invoke(null, new MyCustomEventArgs() { Foo = "Bar" });
        }
    }
}

class MyCustomEventArgs : EventArgs
{
    public string Foo { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
        myClass.MyEvent += new EventHandler<MyCustomEventArgs>(myClass_MyEvent);

        for (int i = 0; i < 9; i++)
        {
            myClass.MyMethod(i);
        }
    }

    //This is the method signature that you need to use to handle the event
    static void myClass_MyEvent(object sender, MyCustomEventArgs e)
    {
        Console.WriteLine(e.Foo); // prints "Bar"
        //Do Stuff
    }

    //If you need to handle more than one type of custom event args
    static void myClass_MyEvent<T>(object sender, T e) where T : EventArgs
    {
        //Do Stuff
    }
}
于 2014-08-28T14:18:59.297 に答える