在C#编程中方法的回调有以下几种方式
通过接口、通过委托、定时回调、多线程回调,异步回调
下面就以代码的形式来讲解这种方式
通过接口回调
代码示例如下
定义接口,定义了一个Run 方法:
interface ICallBack { void Run(); }
定义实现接口的类,并实现接口中定义的方法,方法的作用就是输出当前时间:
class CallBackClass:ICallBack { public void Run() { Console.WriteLine(DateTime.Now); } }
定义“控制回调器“类,定义一个接口类型的字段,用于引用回调对象。定义一个ByInterface方法,用于执行回调:
class Controller { //接口回调 private readonly ICallBack _callBackObject = null; public Controller(ICallBack obj) { this._callBackObject = obj; } public void ByInterface() { Console.WriteLine("敲击任意键显示当前时间,ESC键退出..."); while (Console.ReadKey(true).Key != ConsoleKey.Escape) { this._callBackObject.Run(); } } }
在Main方法中执行:
static int Main(string[] args) { Controller controller = new Controller(new CallBackClass()); controller.ByInterface(); return 0; }
执行结果:
敲击任意键显示当前时间,ESC键退出... 2015/08/10 16:03:22 |
大家对于在Controller类中ICallBack接口变量的使用有什么看法?
我觉得在控制回调器中用接口类型做字段,无疑会降低类与类之间的耦合度,不局限于某一特定的类,只要是实现了接口的对象都可以被调用,这样的程序设计才是被提倡的。
通过委托实现回调
关于委托有这样一句话:.NET 来通过委托提供了一种回调函数机制
所以说使用委托实现回调是最直截了当的的方式了,下面是代码示例。
控制回调器类代码
class Controller { //定义一个委托类型的字段 private Action showTime = null;
//构造函数内接收外界提供的方法 public Controller(Action showTime) { this.showTime += showTime; } public void ByDelegate() { Console.WriteLine("敲击任意键显示当前时间,ESC键退出..."); while (Console.ReadKey(true).Key != ConsoleKey.Escape) { this.showTime(); } } }
在Main方法中执行:
static int Main(string[] args) { Controller controller = new Controller(new Action(()=>Console.WriteLine(DateTime.Now))); controller.ByDelegate(); }
执行结果和通过接口回调的示例一样,在此就不展示结果了
上述代码中的红字为lambda表达式写的匿名方法;
由于委托允许动态的添加(+=)和移除(-=)回调方法,所以比接口使用起来更加灵活
通过定时回调
这种方式应用场景比较特殊,需要以固定的时间间隔调用某个方法。
利用了.NET Framework提供的Timer类,定时回调一个满足TimerCallBack委托要求的方法,此委托定义如下:
public delegate void TimerCallback(object state);
该委托定义了一个object类型参数的方法 Timer类构造函数如下:
public Timer(TimerCallback callback, object state, int dueTime, int period)
参数解析:
callback:定时回调的方法
state:向回调方法传递的参数
dueTime:开发执行回调方法之前延迟的时间,单位是秒。设为0为立即调用回调方法
period:执行回调方法的间隔秒数
示例如下:
public class TaskInfo { public int Count = 0; } static class Program { static void Main() { var ti=new TaskInfo(); var tm = new Timer( obj => { var taskInfo = obj as TaskInfo; taskInfo.Count++; Console.WriteLine(taskInfo.Count); } , ti, 0, 1000); Console.ReadKey(); tm.Dispose(); } }
上述代码中红字为匿名函数,使用了lambda表达式。
关于多线程回调和异步回调下篇再续~谢谢