C#中的回调
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/667742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Callbacks in C#
提问by Malfist
I want to have a library that will have a function in it that accepts an object for it's parameter.
我想要一个库,里面有一个函数,它接受一个对象作为它的参数。
With this object I want to be able to call a specified function when X is finished. The function that will be called is to be specified by the caller, and X will be done and monitored by the library.
有了这个对象,我希望能够在 X 完成时调用指定的函数。将被调用的函数由调用者指定,X 将由库完成和监控。
How can I do this?
我怎样才能做到这一点?
For reference I'm using C# and .NET 3.5
作为参考,我正在使用 C# 和 .NET 3.5
采纳答案by bendewey
Two options for you:
两种选择:
Have the function accept a delegate(
Action
for a callback that doesn't return anything,Func
for one that does) and use an anonymous delegate or Lambda Expression when calling it.Use an interface
Using a delegate/lambda
使用委托/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"));
}
If your callback needs to have something passed to it, you can use a type parameter on Action
:
如果你的回调需要传递一些东西,你可以在 上使用类型参数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));
}
If it needs multiple arguments, you can add more type parameters to Action
. If you need a return type, as mentioned use Func
and make the return type the lasttype parameter (Func<string, int>
is a function accepting a string and returning an int.)
如果它需要多个参数,你可以添加更多类型参数到Action
. 如果您需要返回类型,如上所述,请使用Func
并使返回类型成为最后一个类型参数(Func<string, int>
是一个接受字符串并返回 int 的函数。)
More about delegates here.
更多关于这里的代表。
Using an interface
使用接口
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);
}
回答by Ed S.
The object in question will need to implement an interface provided by you. Take the interface as a parameter, and then you can call any method that the interface exposes. Otherwise you have no way of knowing what the object is capable of. That, or you could take a delegate as a parameter and call that.
有问题的对象将需要实现您提供的接口。把接口作为参数,然后就可以调用接口暴露的任何方法。否则,您将无法知道对象的功能。那,或者您可以将委托作为参数并调用它。
回答by Jon Skeet
Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.
听起来像是委托的完美秘诀 - 特别是,委托回调正是在 .NET 中的异步模式中处理这种情况的方式。
The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.
调用者通常会向您传递一些状态和一个委托,您将它们都存储在您拥有的任何上下文中,然后调用委托将状态和您可能拥有的任何结果传递给它。
You could either make the state just object
or potentially use a generic delegate and take state of the appropriate type, e.g.
您可以使状态只是object
或可能使用通用委托并采用适当类型的状态,例如
public delegate void Callback<T>(T state, OperationResult result)
Then:
然后:
public void DoSomeOperation(int otherParameterForWhateverReason,
Callback<T> callback, T state)
As you're using .NET 3.5 you might want to use the existing Func<...>
and Action<...>
delegate types, but you mayfind it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)
当您使用 .NET 3.5 时,您可能希望使用现有
类型Func<...>
和Action<...>
委托类型,但您可能会发现声明自己的类型会更清晰。(该名称可能会更清楚地说明您使用它的目的。)
回答by Cory McCarty
Is there a reason not to have your library provide a public event to be fired when the operation is complete? Then the caller could just register to handle the event and you don't have to worry about passing around objects or delegates.
是否有理由不让您的图书馆提供在操作完成时触发的公共事件?然后调用者可以注册来处理事件,而您不必担心传递对象或委托。
The object implementing an interface you have provided would work, but it seems to be more the Java approach than the .NET approach. Events seem a bit cleaner to me.
实现您提供的接口的对象可以工作,但它似乎更像是 Java 方法而不是 .NET 方法。事件对我来说似乎更清晰一些。
回答by Vijay Bansal
You can use System.Action available in C#.NET for callback functions. Please check this sample example:
您可以将 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);
}
}