【问题标题】:Callbacks in C#C#中的回调
【发布时间】:2010-10-14 15:24:52
【问题描述】:

我想要一个库,里面有一个函数,它接受一个对象作为它的参数。

有了这个对象,我希望能够在 X 完成时调用指定的函数。调用的函数由调用者指定,X 由库完成并监控。

我该怎么做?

作为参考,我使用的是 C# 和 .NET 3.5

【问题讨论】:

  • 我怀疑您的答案包含门、事件或两者。但是,在阅读了您的问题几次之后,我无法理解您的问题。

标签: c# .net callback


【解决方案1】:

两种选择:

  1. 让函数接受 delegateAction 表示不返回任何内容的回调,Func 表示接受的回调)并在调用时使用匿名委托或 Lambda 表达式。

  2. 使用界面

使用委托/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&lt;string, int&gt; 是一个接受字符串并返回int 的函数。)

更多关于代表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);
}

【讨论】:

  • 我冒昧地扩展了这个出色的答案,以在我找到它时对我有帮助。显然,如果您不关心更改,请回滚。无论如何感谢您的帮助!
【解决方案2】:

听起来像是委托的完美秘诀 - 特别是,带有委托的回调正是 .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&lt;...&gt;Action&lt;...&gt; 委托类型,但您可能会发现声明自己的类型更清晰。 (这个名称可能会让您更清楚地使用它。)

【讨论】:

【解决方案3】:

相关对象需要实现您提供的接口。将接口作为参数,然后就可以调用接口暴露的任何方法。否则,您将无法知道该对象的能力。那,或者您可以将委托作为参数并调用它。

【讨论】:

    【解决方案4】:

    是否有理由不让您的库提供在操作完成时触发的公共事件?然后调用者只需注册即可处理事件,而您不必担心传递对象或委托。

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

    【讨论】:

    【解决方案5】:

    您可以将 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);
            }
        }
    

    【讨论】:

    • 这不是回调的替代方案; 一个回调。
    猜你喜欢
    • 1970-01-01
    • 2011-10-16
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2013-12-01
    • 2011-01-18
    相关资源
    最近更新 更多