17

コードは次のようになります。

時計:

public class Clock
{
    public event Func<DateTime, bool> SecondChange;

    public void Run()
    {
        for (var i = 0; i < 20; i++)
        {
            Thread.Sleep(1000);

            if (SecondChange != null)
            {
                //how do I get return value for each subscriber?
                Console.WriteLine(SecondChange(DateTime.Now));
            }
        }
    }
}

DisplayClock:

public class DisplayClock
{
    public static bool TimeHasChanged(DateTime now)
    {
        Console.WriteLine(now.ToShortTimeString() + " Display");
        return true;
    }
}

LogClock:

public class LogClock
{
    public static bool WriteLogEntry(DateTime now)
    {
        Console.WriteLine(now.ToShortTimeString() + " Log");
        return false;
    }
}

コードを実行するには:

var theClock = new Clock();
theClock.SecondChange += DisplayClock.TimeHasChanged;
theClock.SecondChange += LogClock.WriteLogEntry;
theClock.Run();

その他の質問は次のとおりです。

  • 各サブスクライバーが値を返すのは良い習慣ですか?
  • デリゲートを手動で宣言するのではなく、イベントリターンタイプとしてAction / Funcを宣言するのは良い習慣ですか?
4

2 に答える 2

31

を使用しDelegate.GetInvocationListます。

if (SecondChange != null)
{
    DateTime now = DateTime.Now;
    foreach (Delegate d in SecondChange.GetInvocationList())
    {
        Console.WriteLine(d.DynamicInvoke(now));
    }
}

デリゲートを手動で宣言するのではなく、Action / Funcを使用するのは良い習慣ですか?

はい。EventHandler<T>ただし、ベストプラクティスは、の代わりにイベントを使用することですFunc<..., TResult>EventHandler<T>は戻り値をサポートしていませんが、戻り値を持つ.NETイベントがいくつかあるという点である程度正当化されます。として使用するカスタムEventArgsサブクラスに設定可能なプロパティがある方がよいと思いますT。これは、のようなものに見られるパターンKeyEventArgs.Handledです。このように、EventHandler<T>このプロパティを取得および設定することにより、を使用でき、サブスクライバーは限られた範囲で応答を調整することもできます。

于 2009-08-06T04:46:26.603 に答える
1

デリゲートの代わりにAction/Funcを使用するのはまったく問題ないと思います。

しかし、イベントはそのように使用されることは想定されていません。それらは無期限にトリガーされるため、すべてのパラメーターがわからないだけです。

本当に必要なのはおそらく次のとおりです。

  1. 時計にはポリモーフィズムを使用します。
  2. ビジター/サブスクライバー/オブザーバーパターンを使用して、それらの値を取得します。

したがって、コードは次のようになります。

var theClock = new Clock();
theClock.AddSecondsSubscriber(new DisplayClock());
theClock.AddSecondsSubscriber(new LogClock());
theClock.RunAndExecuteVisitors( theBoolResultYouNeed => Console.WriteLine(theBoolResultYouNeed) );
于 2009-08-06T05:01:44.920 に答える