zoukankan      html  css  js  c++  java
  • C#深度学习の委托深度解析

    一、我们在使用C#的过程中,不可避免的用到了委托。

    委托的本质是什么呢?

    从语法上看,委托是对方法的抽象封装,例如:public void print1(),public void print2(),我们可以抽象化,public delegate void Print();用Print p来声明,委托需要实例化和调用,类似于c++中的函数模板;

    从功能上看,委托主要是方法的指针,用以方便实现函数的回调、调用(异步等)。

    直观上,委托的作用有方法(函数)回调、方法(函数)接收值(listener),方法(函数)多线程调用、传值等等。

    本质上,delegate是一个类,同关键字class和interface平级的,这个类中包含方法所属的类实例的地址、方法的地址,以及下个委托的引用(因此委托是链式结构的)。

    以下我们以实例展开委托声明、实例化、调用等技巧。

    二、委托的声明

    C#中借用delegate关键字,C#的编译器一遇到delegate,在翻译C#的时候就被翻译成类似于函数模板的东西。delegate刻意定义在类的内部,也可以定义在外部,和类没有关系。

    public delegate void Print();              //无参数,无返回值的委托
    
    public delegate <out string>Print();   //无参数,返回string的委托
    
    public delegate<out string,in string>Print(string str);  //string参数,返回string的委托
    
    .net3.5,系统定义了无参和有参的委托Action和Func关键字
    
    public Action  本质就是public delegate void的转定义
    
    public Func    本质是public delegate <out string>

    用法:

    public Action<string> action;
    
    public Func<string> func;

    委托的方法必须在形式上和委托的声明一致

    三、委托的赋值

    public NoparamDelegate noParam = new NoparamDelegate(doSomething_forNoparamDelegate);    //new 实现
    
    public NoparamDelegate noparam_for_lambd = () =>                                                                            //lambd表达式直接赋值
    {
    Console.WriteLine("no param,form lambd,test");
    };
    public NoparamDelegate noparam_for_function = doSomething_function;                                            //方法直接赋值
    
    public static void doSomething_forNoparamDelegate()
    {
    Console.WriteLine("no param,form test");
    }
    
    public static void doSomething_function()
    {
    Console.WriteLine("no param,form function, test");
    }

    四、委托的调用

    //委托调用-普通方法
    doSomething();

    //委托调用invoke
    doSomething?.Invoke();
    oneParam?.Invoke("one param,form test");

    //异步调用

    doSomething?.BeginInvoke(complete, null); //object标识附加信息
    IAsyncResult ret = func_oneparam?.BeginInvoke("transmit赋值,异步调用,", null, null);     //ret.IsCompleted, ret.AsyncWaitHandle.WaitOne(100)等用于轮询过程
    Console.WriteLine("开始其他工作!.."); 
    string strRet = func_oneparam?.EndInvoke(ret);
    Console.WriteLine(strRet);

    委托的BeginInvoke有两个或三个参数(重载)

    param1:string,参数

    param2:回调函数,异步方法完成后调用

    param3:object形式的附加信息

    返回值:IAsyncResult 类型,我们记作ret

    ret中有属性IsCompleted和AsyncWaitHandle,可以用以轮询异步方法调用的方法

    string strRet = func_oneparam?.EndInvoke(ret);  //在需要的地方获取异步执行结果,如果没执行完,将阻塞调用线程,直至获取结果

    五、委托链

    对于多个委托方法,.net定义了委托链的概念

    Delegate主要定义了Combine(简写+=),Remove(简写-=)等方法

    Action delegateSet = null;
    delegateSet = (Action)Delegate.Combine(actionChainOne,actionChainTwo);

    下面是一段示例代码:

      public class Test
        {
            public delegate void Print();
            Print p;
            public void method1()
            {
                Console.WriteLine("m 1");
            }
            public void method2()
            {
                Console.WriteLine("m 2");
            }
    
            public void method3()
            {
                Console.WriteLine("m 3");
            }
            public void method4()
            {
                Console.WriteLine("m 4");
            }
    
            public void combine()
            {
                p += method1;
                p += method2;
                p += method3;
                p += method4;
            }
            public void run()
            {
                Delegate[] myDelegates = p.GetInvocationList();
                foreach (var myDelegate in myDelegates)
                {
                    Print m1 = (Print)myDelegate;//注意此处需强转
                    m1.Invoke();
                }
            }
    }
        class Program
        {
            static void Main(string[] args)
            {
                Test test = new Test();
                test.combine();
                test.run();
    
                Console.ReadKey();
            }
        }

    有交流沟通,请加群:568055323

  • 相关阅读:
    ngnix+uwsgi+django 部署mezzanine
    shell三剑客之find
    Flask常见面试问题
    redis宕机如何解决?如果是项目上线的宕机呢?
    UiPath,容智Ibot在线接单,有需求的欢迎过来
    CORS和CSRF
    JWT黑名单和白名单
    Django项目常见面试问题
    降低Redis内存占用
    Redis-缓存有效期与淘汰策略
  • 原文地址:https://www.cnblogs.com/xietianjiao/p/9935361.html
Copyright © 2011-2022 走看看