非同期TCPソケットを使用する小さなマルチスレッドアプリを実行していますが、ポイントを取得します。カスタムイベントを使用してフォームとデリゲートから値を読み取りますイベントが使用すると、終了時に文字列が返されます。
ここで私の質問は:それは正しいですか?イベントから値を返しても大丈夫ですか?またはこれを行うためのより良い方法はありますか? (フォームへの単純なデリゲートを使用して値を読み取るなど)
イベントから値を返すのはしばしば厄介です。実際には、イベントに渡され、WinForms FormClosingイベントのCancelプロパティと同様に、イベントの発生後にチェックされるカスタムEventArgsのセットに書き込み可能なプロパティを含める方がはるかに簡単であることがわかりました。
私はそれが良い考えだとは思わない...イベントは基本的にマルチキャストデリゲートであるため、複数のハンドラが存在する可能性があります。その場合、どの戻り値を使用しますか?
私が考えることができる最も近い例は、WinFormsのFormClosingイベントです。 eventArgs.Cancelプロパティをtrueに設定することにより、フォームでイベントをキャンセルできます。同様のことを行うには、戻り値をそのクラスのプロパティとして使用して、独自のイベント引数クラスを定義します。その後、イベントを発生させるたびにイベントargsオブジェクトを渡します。イベントを発生させた人は誰でも戻り値のイベントargsオブジェクトを検査できます。イベントを受信している他の人は、イベント引数オブジェクトを検査または変更することもできます。
更新:AppDomain.AssemblyResolve イベントに遭遇しましたが、値を返すイベントのようです。値を返すデリゲート型を宣言し、そのデリゲート型でイベントを定義するだけでよいようです。ただし、このような独自のイベントを作成しようとしたことはありません。イベント引数でプロパティを使用する1つの利点は、イベントのすべてのサブスクライバーが以前のサブスクライバーが返したものを確認できることです。
私はこれが投稿後の年齢であることを知っていますが、他の誰かがこのスレッドに出くわした場合のダスティン・キャンベルの答えを説明するためのコード付きコメントを追加することを考えました。私はこの投稿に出くわしましたが、ベストプラクティスとは何かを判断しようとしていましたが、これが答えの意味です。
独自のカスタムイベントハンドラークラスを作成する
public class myCustomeEventArgs:EventArgs
{
public bool DoOverride { get; set; }
public string Variable1 { get; private set; }
public string Variable2{ get; private set; }
public myCustomeEventArgs(string variable1 , string variable2 )
{
DoOverride = false;
Variable1 = variable1 ;
Variables = variable2 ;
}
}
したがって、イベントデリゲートを作成するときは、作成したイベント引数を次のように使用します。
public delegate void myCustomeEventHandler(object sender, myCustomeEventArgs e);
イベントを発生させるクラスでは、イベントを宣言します。
public event myCustomeEventHandler myCustomeEvent;
したがって、イベントをリッスンするクラスでイベントをトリガーするときは、イベントの本体だけで設定できますe.DoOverride = true;イベントを起動するクラスで宣言されるためです。
たとえば、火災イベント:
if(myCustomeEvent != null)
{
var eventArgs = new myCustomeEventArgs("Some Variable", "Another Varaible");
myCustomeEvent(this, eventArgs);
//Here you can now with the return of the event work with the event args
if(eventArgs.DoOverride)
{
//Do Something
}
}
注:最後のイベントのみが結果を返します。
class Program
{
static event Func<string, bool> TheEvent;
static void Main(string[] args)
{
TheEvent += new Func<string, bool>(Program_TheEvent);
TheEvent +=new Func<string,bool>(Program_TheEvent2);
TheEvent += new Func<string, bool>(Program_TheEvent3);
var r = TheEvent("s"); //r == flase (Program_TheEvent3)
}
static bool Program_TheEvent(string arg)
{
return true;
}
static bool Program_TheEvent2(string arg)
{
return true;
}
static bool Program_TheEvent3(string arg)
{
return false;
}
}
これがベストプラクティスであるかどうかはわかりませんが、このようにしました。
Func<DataRow, bool> IsDataValid;
// some other code ....
isValid = true;
if (IsDataValid != null)
{
foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList())
{
isValid &= func(Row);
}
}
イベントが値を返し、複数のハンドラーが登録されている場合、イベントは最後に呼び出されたハンドラーの結果値を返します。 http://blogs.msdn.com/b/deviations/archive/2008/11/27/event-handlers-returning-values.aspx で例を探します
このようにEventArgsのプロパティをループし、そのX値とY値を引き出しました。
private void navBarControl1_Click(object sender、EventArgs e){int _x = 0; int _y = 0;
Type t = e.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(t.GetProperties());
foreach (PropertyInfo prop in props)
{
if (prop.Name == "X")
{
object propValue = prop.GetValue(e, null);
_x = Convert.ToInt32(propValue);
}
if (prop.Name == "Y")
{
object propValue = prop.GetValue(e, null);
_y = Convert.ToInt32(propValue);
}
}