派生クラスで基本クラスのイベントを提起するc#
-
13-09-2019 - |
質問
私は基本クラスのdockedtoolwindow:フォームと、dockedtoolwindowに由来する多くのクラスを持っています。イベントを保持してdockedtoolwindowオブジェクトに割り当てるコンテナクラスがありますが、子供クラスのイベントを呼び出したいと思います。
私は実際にこれを実装する方法について質問があります MSDNサイト 私にするように言っています。以下のこのセクションは、私に問題を示しています:
// The event. Note that by using the generic EventHandler<T> event type
// we do not need to declare a separate delegate type.
public event EventHandler<ShapeEventArgs> ShapeChanged;
public abstract void Draw();
//The event-invoking method that derived classes can override.
protected virtual void OnShapeChanged(ShapeEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<ShapeEventArgs> handler = ShapeChanged;
if (handler != null)
{
handler(this, e);
}
}
確かにこの例はコンパイルされて動作しますが、「シェイプチェンジ」を「移動」(フォームから得たイベント)に置き換えると、 +=または - =なしで右側に移動できないというエラーがあります。 Shapeeventargsジェネリックタグも削除しました。
なぜこれが機能していないのかについては何かインコがありますか?クラス内で宣言されたイベントと継承されたイベントの違いは何ですか?
解決
基本クラスのイベントを直接発射することはできません。これがまさにあなたがあなたを作らなければならなかった理由です OnShapeChanged
方法 protected
それ以外の private
.
使用する base.onmove() 代わりは。
他のヒント
C#言語仕様から、セクション10.7(強調追加):
イベントの宣言を含むクラスまたは構造体のプログラムテキスト内で、特定のイベントはフィールドのように使用できます. 。この方法で使用するには、イベントを抽象的または外部ではないか、イベントアクセサリデクレーションを明示的に含めてはなりません。このようなイベントは、フィールドを許可する任意のコンテキストで使用できます。フィールドには、イベントに追加されたイベントハンドラーのリストを指す代表者(§15)が含まれています。イベントハンドラーが追加されていない場合、フィールドにはnullが含まれています。
したがって、移動イベントをフィールドのように扱うことができない理由は、異なるタイプ(この場合はスーパークラス)で定義されているためです。私は、デザイナーがイベントへの意図しないサルキーを防ぐためにこの選択をしたという @WOMPの推測に同意します。無関係なタイプ(イベントを宣言するタイプから派生していないタイプ)がこれを行うことを許可することは明らかに悪いようですが、派生タイプであっても、望ましくないかもしれません。彼らはおそらくイベント宣言を行うために構文を含める必要があったでしょう private
また protected
フィールドスタイルの使用に関しては、私の推測では、彼らはそれを完全に禁止することを選択したと思います。
違いは範囲です。クラス内では、イベントの代表者がどのように処理されるかを制御できますが、クラスは基本クラスが何をしているかを制御できません。イベントとそのハンドラーで、いくつかのクレイジーな舞台裏のことをしているかもしれません。 Moveイベントを単に「再割り当て」した場合、イベントのマルチキャストデリゲートリストを一掃することになります。
私は彼らが非常に安全でない練習であるため、彼らがこれにコンパイラの制限を置いており、基本的にどんな子孫クラスにも親のイベントモデルを破壊する能力を与えるだろうと推測しています。
イベント自体が定義されているクラスに投稿したコードのみが必要です。すべての派生クラスは、コピーなどなしで、onshapeChanged()またはonmove()を直接呼び出す必要があるため、クラスでそのコードをまったく書き込むべきではありません(移動イベントはベースで定義されているため)。
派生クラスで何らかの処理を行う必要がある場合(コレクションクラスをいじる必要があるかもしれませんか?)、仮想onxxx呼び出しを上書きし、base.onxxx()を呼び出す前に詰め込みます。 MSDNの記事では、サークルクラスはDockedToolWindowクラスに対応しています。派生したクラスでも同じパターンが利用できるようにする必要があります。