在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
1、委托可确保回调方法是类型安全的; 2、委托可以顺序调用多个方法,并支持静态方法和实例方法; 3、委托封装实例方法是非常有用的,因为对象内部的代码可以访问对象的实例方法成员,这就意味着对象可以维护一些状态,并且在回调方法执行期间用到这种状态; 4、委托实际上是类,因为编译器会为委托生成一个完整的类,所以在可以定义类的地方,就可以定义委托; 5、Delegate类定义了两个只读的公共实例属性:Target和Method;Target返回一个对象引用,该对象就是方法回调时要操作的那个对象,如果委托对象封装了一个静态方法,那么Target将返回Null;Method属性返回一个System.Reflection.MethodInfo对象引用(标识回调方法);
协变与反协变协变(convariance):指的是一个方法返回从委托的返回类型派生的一个类型; 反协变(contra-variance):指的是一个方法的参数类型可以是委托的参数类型的基类型;
internal delegate object MyCallback(int s);
public class Delegate_covariance_contra_variance { private static string SomeMethod(object s) { Console.WriteLine(s.ToString()); return s.ToString(); }
public static void Test() { //Error:“SomeMethod(object)”的重载均与委托“MyCallback”不匹配 MyCallback call = new MyCallback(SomeMethod);
call(1); }
上面的代码编译时会出错,分析一下: 首先,SomeMethod的返回类型(String)是继承自委托返回类型(Object),所以这种协变是允许的; 其次,SomeMethod的参数类型(Object)是委托的参数类型(int)的基类,符合 反协变的定义,但是这种反协变是无法通过编译的,因为协变与反协变都不支持值类型和Void:因为值类型和void的存储结构式变化的,而引用类型的存储结构始终是一个指针; 最后,修改方法就是将委托的参数类型改为引用类型。 internal delegate object MyCallback(string s);
对委托链调用进行更多控制委托链调用要注意两个问题: 1、 除最后一个返回值之外,回调方法的所有返回值都会被丢弃; 2、 如果被调用的委托中有一个抛出了异常或者堵塞了相当长一段时间,就会停止调用后续所有对象。
为此,MulticastDelegate类提供了一个实例方法GetInvocationList,
private static String GetComponentStatusReport(GetStatus status) { // If the chain is empty, there抯is nothing to do. if (status == null) return null; // Use this to build the status report. StringBuilder report = new StringBuilder();
// Get an array where each element is a delegate from the chain. Delegate[] arrayOfDelegates = status.GetInvocationList();
// Iterate over each delegate in the array. foreach (GetStatus getStatus in arrayOfDelegates) {
try { // Get a component's status string, and append it to the report. report.AppendFormat("{0} {1} {2}", getStatus(),getStatus.Target+":"+getStatus.Method, Environment.NewLine); } catch (InvalidOperationException e) { // Generate an error entry in the report for this component. Object component = getStatus.Target; report.AppendFormat( "Failed to get status from {1}{2}{0} Error: {3}{0}{0}", Environment.NewLine, ((component == null) ? "" : component.GetType() + "."), getStatus.Method.Name, e.Message); } }
// Return the consolidated report to the caller. return report.ToString(); }
C#为委托提供的语法便利 主要介绍了委托的简便写法,这里有一个定义匿名方法(anonymous method),要注意三点: 1、 在编写匿名方法的时候,在代码中的delegate关键字后加入这个指定名称(Object obj); internal sealed class AClass { private static void CallbackWithoutNewingADelegateObject() { ThreadPool.QueueUserWorkItem( delegate(Object obj) { Console.WriteLine(obj); }, 5); } } 2、 匿名方法标识为private,这会禁止在类型内部定义的任何代码访问这个方法; 匿名方法标识为static,这是因为代码没有访问任何实例方法成员,不过,代码可以引用类中定义的静态字段或静态方法; internal sealed class AClass {
private static string m_str;
private static void CallbackWithoutNewingADelegateObject() { ThreadPool.QueueUserWorkItem( delegate(Object obj) { Console.WriteLine( m_str+":"+obj); }, 5); } }
3、 如果CallbackWithoutNewingADelegateObject方法不是静态的,那么匿名方法的代码就可以包含对实例成员的引用; internal sealed class AClass {
private int m_i;
private void CallbackWithoutNewingADelegateObject1() { ThreadPool.QueueUserWorkItem( delegate(Object obj) { Console.WriteLine(m_i + ":" + obj); }, 5); } }
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论