C#中的回调

时间:2009-03-20 20:01:22

标签: c# .net callback

我希望有一个库中有一个函数,它接受一个对象作为参数。

使用此对象,我希望能够在X完成时调用指定的函数。将被调用的函数由调用者指定,X将由库完成并监视。

我该怎么做?

供参考我正在使用C#和.NET 3.5

5 个答案:

答案 0 :(得分:40)

有两种选择:

  1. 让函数接受一个delegateAction表示没有返回任何内容的回调,Func表示一个回复,并使用匿名委托或Lambda表达式在打电话时。

  2. 使用界面

  3. 使用delegate / lambda

    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上使用类型参数:

    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的函数。)< / p>

    有关代表here的更多信息。

    使用界面

    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);
    }
    

答案 1 :(得分:6)

听起来像代表的完美配方 - 特别是,与委托的回调正是如何在.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<...> 委托类型,但您可能发现它使得更清楚地声明您自己的类型。 (该名称可能会使您更清楚地使用它。)

答案 2 :(得分:1)

有问题的对象需要实现您提供的界面。将接口作为参数,然后您可以调用接口公开的任何方法。否则你无法知道对象的能力。那,或者你可以把一个委托作为参数并调用它。

答案 3 :(得分:1)

是否有理由不让您的图书馆在操作完成时提供公开事件?然后调用者可以注册以处理事件,您不必担心传递对象或委托。

实现您提供的接口的对象可以工作,但它似乎更像是Java方法而不是.NET方法。事件似乎对我来说有点清洁。

答案 4 :(得分:-1)

您可以使用C#.NET中提供的System.Action作为回调函数。请查看此示例示例:

    //Say you are calling some FUNC1 that has the tight while loop and you need to 
    //get updates on what percentage the updates have been done.
    private void ExecuteUpdates()
    {
        Func1(Info => { lblUpdInfo.Text = Info; });
    }

    //Now Func1 would keep calling back the Action specified in the argument
    //This System.Action can be returned for any type by passing the Type as the template.
    //This example is returning string.
    private void Func1(System.Action<string> UpdateInfo)
    {
        int nCount = 0;
        while (nCount < 100)
        {
            nCount++;
            if (UpdateInfo != null) UpdateInfo("Counter: " + nCount.ToString());
            //System.Threading.Thread.Sleep(1000);
        }
    }