.NETには組み込みのEventArgs <T>がありますか?


84

単一の引数を持つイベント引数の汎用EventArgsクラスを作成する準備をしています。

public class EventArg<T> : EventArgs
{
    // Property variable
    private readonly T p_EventData;

    // Constructor
    public EventArg(T data)
    {
        p_EventData = data;
    }

    // Property for EventArgs argument
    public T Data
    {
        get { return p_EventData; }
    }
}

その前に、C#には同じ機能が言語に組み込まれていますか?C#2.0が出たときにそのようなものに出くわしたことを覚えているようですが、今はそれを見つけることができません。

別の言い方をすれば、独自の汎用EventArgsクラスを作成する必要がありますか、それともC#が提供しますか?ご協力いただきありがとうございます。


9
Eventhandler<T>
ご覧になった

1
EventArgs<T>CAB / SCSFベースのコードで見たことがあるかもしれません。これは、CAB / SCSFアプリケーションでは非常に一般的です。フレームワークの一部ではありません、EventArgs <T>の実装があります。
ショーンウィルソン

回答:


66

いいえ、あなたはおそらく考えていたでしょう EventHandler<T>、特定のタイプのEventArgsのデリゲートを定義できるようにすることを。

個人的には、それEventArgs<T>がぴったりだとは思いません。イベント引数で「ペイロード」として使用される情報は、私の意見では、その使用法と期待されるプロパティを非常に明確にするためのカスタムクラスである必要があります。ジェネリッククラスを使用すると、意味のある名前を配置できなくなります。(「データ」は何を表していますか?)


50
データ中心のMPIのようなアプリケーションでは、開発者が組み込みのタイプセーフなサブスクリプション/登録システム(.NETイベントおよびデリゲート)を活用できるように、データ処理用にEventArgs <T>を配置するのが非常に一般的です。データを転送するためだけにEventArgsサブクラスを作成することはまったく意味がないためです。データを転送することを目的としている場合は、転送されるデータに関係なく、個別に使用するためにサブクラス化できるEventArgs <T>を定義する方がおそらく理にかなっています。TL:DRこの回答のこの最初の部分は事実に基づいて正確であり、2番目の部分は主観的/意見です。
ショーンウィルソン

1
私はあなたが正しいと思います...私をここに連れて行った怠惰に抵抗してください。怠惰な開発者がTuple <、>を使用するようなものです。ひどいもの。
CRice 2014

良い点ですが、これは基本的に、MicrosoftがControlsクラスにTagプロパティを追加したときと同じことを行うことになります。もちろん、cozのMSがそれを行っただけで、正しくはなりません。
ケンリチャーズ

1
私は最初のコメンテーターに同意します。この回答の後半全体は、建設的ではなかった主観的な意見/コード宗教です。:(
BrainSlugs83 2018

5
どのようにないのEventHandler <顧客>のEventHandler <注文>はより任意の少ない情報伝えるCustomerEventHandlerまたはOrderEventHandlerを
奇妙な2018

33

私はここですべての「純粋主義者」を理解しているわけではないと言わなければなりません。つまり、すでにバッグクラスが定義されている場合(すべての詳細、プロパティなどが含まれています)、イベント/引数メカニズム、署名スタイルに従うためだけに、ハックによって不要なクラスが1つ追加されるのはなぜですか?事は-.NETにあるすべてではない-またはそのことについては「欠けている」-「良い」-MSは何年もの間それ自体を「修正」している...私はただ行って作成する-私がしたように-そのように必要だったので-そして多くの時間を節約しました


3
この場合、「純粋主義者」のポイントは、意図を可能な限り明確にすることです。本番アプリには、これらのEventArgsクラスが数十あります。1年後、Reedのアドバイスに従って、カスタムEventArgsクラスを作成すると、私が何をしたかを理解しやすくなります。
David Veeneman 2011年

9
誰かにラベルを付けるつもりはありませんでした:)ポイントはイベントの「ジェネリック」にあります-ダースの異なるイベントが必要な場合は、わかりました。ただし、Tの性質が事前にわからない場合(実行時にのみ知られている場合)は、一般的なイベントが必要になります。したがって、ジェネリック、任意の数のタイプ、不明なものを扱うのに適したアプリがある場合は、ジェネリックイベントも必要です。すなわち、すべての問題のためのクリーンカットソリューションはありませんか、親指のルールは親指のちょうどルールです-そしてそれは、私は純粋主義者によって意味したものですが、各ソリューションは異なっている、あなたは物事、長所と短所を比較検討する必要がある
NSGaga-mostly-非アクティブ

2
デザインは白黒ではないので、ここではNSGagaに同意する傾向があります。時々、「速くて汚い」が適切です。この言語は、ほとんどのユースケースに適合するように機能が豊富である必要があります。何が適切かを決めるのは開発者次第です。MSが言語を制限して「優れた」設計を強制しようとした最後の試みはWPFで、.NET APIを大幅にハンディキャップしてXAMLの使用を強制しようとしたとき、それはひどいものでした。
robear 2018年

9

それは存在します。少なくとも、今はそうです。

あなたは見つけることができるDataEventArgs<TData>インスタンスのために、いくつかの異なるマイクロソフトアセンブリ/名前空間にMicrosoft.Practices.Prism.Events。ただし、これらはプロジェクトに含めるのが自然ではない可能性がある名前空間であるため、独自の実装を使用するだけで済みます。


私は、このような一般的なEventArgsクラスをいつ、なぜ使用するかに関する推奨事項と考慮事項を見つけようとしています。参照:stackoverflow.com/questions/15766219/...
ウルフÅkerstedt

ここでは、汎用のEventArgsを使用して決定する際には注意してくださいするにはいくつかの側面があります:stackoverflow.com/questions/129453/...
ウルフÅkerstedt

7

Prismを使用しないことを選択したが、それでも一般的なEventArgsアプローチを試したい場合。

public class GenericEventArgs<T> : EventArgs
{
    public T EventData { get; private set; }

    public GenericEventArgs(T EventData)
    {
        this.EventData = EventData;
    }
}

//次のサンプルコードを使用して、ObjAddedイベントを宣言します

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;

//次のサンプルコードを使用してObjAddedイベントを発生させます

private void OnObjAdded(TargetObjType TargetObj)
{
    if (ObjAdded!= null)
    {
        ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj));
    }
}

//そして最後に、ObjAddedイベントをサブスクライブできます

SubscriberObj.ObjAdded +=  (object sender, GenericEventArgs<TargetObjType> e) =>
{
    // Here you can explore your e.EventData properties
};

3

組み込みのジェネリックARGSはありません。Microsoft EventHandlerパターンに従う場合は、提案したように派生EventArgsを実装します public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }

ただし、チームスタイルガイドが簡略化を受け入れている場合、プロジェクトでは次のような軽量のイベントを使用できます。

public event Action<object, string> MyStringChanged;

使用法 :

// How to rise
private void OnMyStringChanged(string e)
{
    Action<object, string> handler = MyStringChanged;    // thread safeness
    if (handler != null)
    {
        handler(this, e);
    }
}

// How to handle
myObject.MyStringChanged += (sender, e) => Console.WriteLine(e);

通常、PoCプロジェクトは後者のアプローチを使用します。ただし、専門的なアプリケーションでは、FX copの正当化#CA1009に注意してくださいhttps://msdn.microsoft.com/en-us/library/ms182133.aspx


1

ジェネリック型の問題は、DerivedTypeがBaseTypeを継承しても、EventArgs(DerivedType)がEventArgs(BaseType)を継承しないことです。したがって、EventArgs(BaseType)を使用すると、後でその型の派生バージョンを使用できなくなります。


2
これは明らかに誤りです。「ジェネリック医薬品の共変性と反変性-Microsoft.com」を参照してください。msdn.microsoft.com/ en- us / library / dd799517.aspx
Shaun Wilson

1
@ShaunWilson:どの側面が間違っていますか?共分散インターフェースを定義することもできますIEventArgsが、ジェネリック型パラメーターに関してジェネリックにできるクラスは、にフィードされないデリゲートだけDelegate.Combineです。で使用されるデリゲートはDelegate.Combine共変であってはなりません。たとえば、Action<DerivedType>を型のフィールドに格納できますAction<BaseType>が、後でCombineインスタンスを使用してそれを試みるAction<BaseType>と失敗します。
スーパーキャット2013

-4

これが存在しない理由は、最終的にこれを実装するためです。次に、Tを入力するときに、イベント引数のデータバッグとして機能する、強く型付けされた明確なプロパティを持つクラスを作成する必要がありますが、実装の途中で、そのクラスをEventArgsから継承させて、それを適切と呼ぶだけでは理由がないことに気づきました。

データバッグに文字列などの基本的なものが必要な場合を除いて、.NETにはおそらくEventArgsクラスが標準であり、単純な目的を果たすことを目的としています。


-1。私は今まさにこの状況にあり、私のペイロードはバスからの「メッセージ」である不変のオブジェクトになります...そして他の場所でも使用されます。カスタムEventArgs ....はここに冗長クラスを作成します。珍しいですが、アプリケーションはそうです。
TomTom
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.