zoukankan      html  css  js  c++  java
  • 总结:CLR Via C#(第15章):委托

    委托

    1、委托可确保回调方法是类型安全的;

    2、委托可以顺序调用多个方法,并支持静态方法和实例方法;

    3、委托封装实例方法是非常有用的,因为对象内部的代码可以访问对象的实例方法成员,这就意味着对象可以维护一些状态,并且在回调方法执行期间用到这种状态;

    4、委托实际上是类,因为编译器会为委托生成一个完整的类,所以在可以定义类的地方,就可以定义委托;

    5Delegate类定义了两个只读的公共实例属性:TargetMethodTarget返回一个对象引用,该对象就是方法回调时要操作的那个对象,如果委托对象封装了一个静态方法,那么Target将返回NullMethod属性返回一个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()

            {

    //ErrorSomeMethod(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);

        }

    }

  • 相关阅读:
    计算机视觉(四)
    计算机视觉(三)
    计算机视觉(二)
    计算机视觉(一)
    基于opencv3实现运动物体识别
    tensorRT程序设计框架_4
    Cuda程序的设计-2
    神经网络的快速体验
    STL简介_18
    函数模板-17
  • 原文地址:https://www.cnblogs.com/LeimOO/p/1659103.html
Copyright © 2011-2022 走看看