web-dev-qa-db-ja.com

C#でのコールバック

パラメータのオブジェクトを受け入れる関数を含むライブラリが必要です。

このオブジェクトを使用して、Xが終了したときに指定された関数を呼び出せるようにします。呼び出される関数は呼び出し元によって指定され、Xはライブラリによって実行および監視されます。

これどうやってするの?

参考までに、C#と.NET3.5を使用しています

16
Malfist

あなたのための2つのオプション:

  1. 関数に デリゲートAction 何も返さないコールバックの場合は Func 実行する場合)、それを呼び出すときに匿名デリゲートまたはラムダ式を使用します。

  2. インターフェースを使用する

デリゲート/ラムダの使用

public static void DoWork(Action processAction)
{
  // do work
  if (processAction != null)
    processAction();
}

public static void Main()
{
  // using anonymous delegate
  DoWork(delegate() { Console.WriteLine("Completed"); });

  // using Lambda
  DoWork(() => Console.WriteLine("Completed"));
}

コールバックに何かを渡す必要がある場合は、Actionでtypeパラメーターを使用できます。

public static void DoWork(Action<string> processAction)
{
  // do work
  if (processAction != null)
    processAction("this is the string");
}

public static void Main()
{
  // using anonymous delegate
  DoWork(delegate(string str) { Console.WriteLine(str); });

  // using Lambda
  DoWork((str) => Console.WriteLine(str));
}

複数の引数が必要な場合は、Actionに型パラメーターを追加できます。前述のように、戻り値の型が必要な場合は、Funcを使用して、戻り値の型をlast型パラメーター(Func<string, int>は、文字列を受け取り、intを返す関数です。)

デリゲートの詳細 ここ

インターフェースの使用

public interface IObjectWithX
{
  void X();
}

public class MyObjectWithX : IObjectWithX
{
  public void X()
  {
    // do something
  }
}

public class ActionClass
{
  public static void DoWork(IObjectWithX handlerObject)
  {
    // do work
    handlerObject.X();
  }
}

public static void Main()
{
  var obj = new MyObjectWithX()
  ActionClass.DoWork(obj);
}
40
bendewey

デリゲートの完璧なレシピのように聞こえます。特に、デリゲートを使用したコールバックは、.NETの非同期パターンでこれが処理される方法とまったく同じです。

呼び出し元は通常、いくつかの状態とデリゲートを渡します。両方を取得したコンテキストに格納してから、デリゲートを呼び出して、状態と結果を渡します。

状態をobjectにするか、ジェネリックデリゲートを使用して、適切なタイプの状態を取得することができます。

public delegate void Callback<T>(T state, OperationResult result)

次に:

public void DoSomeOperation(int otherParameterForWhateverReason,
                            Callback<T> callback, T state)

.NET 3.5を使用しているので、既存のFunc<...>およびAction<...>デリゲート型を使用することもできますが、mayすると、独自のデリゲート型を宣言する方が明確になります。 (名前によって、使用目的が明確になる場合があります。)

6
Jon Skeet

問題のオブジェクトは、提供されたインターフェースを実装する必要があります。インターフェイスをパラメータとして使用すると、インターフェイスが公開する任意のメソッドを呼び出すことができます。そうしないと、オブジェクトの機能を知る方法がありません。または、デリゲートをパラメーターとして取り、それを呼び出すことができます。

1
Ed S.

操作が完了したときに発生する公開イベントをライブラリに提供させない理由はありますか?そうすれば、発信者はイベントを処理するために登録するだけで済み、オブジェクトやデリゲートを渡すことを心配する必要はありません。

提供したインターフェースを実装するオブジェクトは機能しますが、.NETアプローチよりもJavaアプローチの方が多いようです。イベントは私には少しすっきりしているようです。

1
Cory McCarty