zoukankan      html  css  js  c++  java
  • C# 委托

    一、前言:每次看到委托和事件,心理面总是不自在,原因大家都懂,但是委托和事件在.NET FrameWork里面的应用非常的广泛,所以熟练的掌握委托和事件对一个.NET开发人员来说是十分重要的,所以花半天的时间来彻底的扫下盲点,争取能carry掉!

    二、概述

    1、作用:委托的作用是将方法作为参数传递给方法

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Delegate
    {
        class Program
        {
            static void Main(string[] args)
            {   
                Program p=new Program();
                p.SayHello("张三");
            }
            public void SayHello(string name)
            {
                ChineseSayHello(name);
            }
    
            private void ChineseSayHello(string name)
            {
                Console.WriteLine("你好:{0}",name);
            }
        }
    }

    上面的代码主要是一个打招呼程序,当你给SayHello()方法输入参数姓名是,该程序就会吊用中文式的SayHello的方法,但是有一个问题,现在这个程序需要国际化,需要填加其他国家的SayHello()方法,如何美国的,那么这个时候应该加一个language参数,来区分不同的国家,下面是改进后的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Delegate
    {
        class SayHello1
        {
            static void Main(string[] args) {
                SayHello1 s1 = new SayHello1();
                s1.SayHello("张三", Country.Chinese);
                s1.SayHello("张三", Country.America);
            }
            public void SayHello(string _name, Country _country)
            {
                switch (_country) {
                    case Country.America: EnglishSayHello(_name); break;
                    case Country.Chinese: ChineseSayHello(_name); break;
                    default: ChineseSayHello(_name); break;
                }
            }
            private void EnglishSayHello(string _name) {
                Console.WriteLine("Hello {0}", _name);
            }
            private void ChineseSayHello(string _name)
            {
                Console.WriteLine("你好 {0}", _name);
            }
        }
        public enum Country { 
    
            //中国
            Chinese,
            //美国
            America
        }
    }

    上面的代码通过枚举和switch判断,解决了国际化的问题,但是这样的代码耦合度太高,试想一下,当我们每加一个国家,SayHello()方法就要改变,这是不妥的,话句话说,就是假设我们加一个韩国的SayHello()的方法,在设计层面上来看它仅仅是加了一个韩国的SayHello的方法,但是从代码和角度看,他改变的是整个SayHello()方法的结构,这是不妥的,中国和美国的SayHello方法不应该因为额外加了一个韩国的SayHello方法所出现的安全问题买单。所以这种方法虽然解决了问题,但是产生了不必要的问题,代码的扩展性很差。

    下面通过委托来解决上面的问题

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Delegate
    {
        //定义一个委托EventHander是微软定义委托的一种标准委托的名字+EventHander
        //定义了一个无返回值,参数为name的委托
        //注意委托定义的位置和string,delegate,SayHello2的位置是一样的,说明委托也应该是个类型,或者说类
        //但是委托的声明方式,却和类不一样。实际上委托最后确实会被编译成一个类.应为delegate是个类,所以任何可以声明类的地方都可以声明委托
    
        public delegate void SayHelloEventHander(string name);
        class SayHello2
        {
            private static void Main(string[] args) {
                SayHello2 s2 = new SayHello2();
                s2.SayHello("张三", s2.ChineseSayHello);
                s2.SayHello("zhangsan", s2.EnglishSayHello);
            }
            public void SayHello(string _name, SayHelloEventHander _sayHello) {
                _sayHello(_name);     
            }
            private void EnglishSayHello(string _name) {
                Console.WriteLine("hello:{0}", _name);
            }
            private void ChineseSayHello(string _name)
            {
                Console.WriteLine("你好:{0}", _name);
            }
        }
    }

    总结:

    <1>委托是一个类,任何可以声明类的地方,都可以声明委托.

    <2>委托可以定义方法的类型和返回值

    <3>通过使用委托,将方法作为参数传递给方法的方式,减少了程序中if else和switch语句出现的次数,增加了程序的可扩展性

    2、委托也是一种数据类型

    (1)、上面的代码中提到了,可以定义类的地方,就可以定义委托,那么我们就可以推断出,委托实际上也是一种数据类型,我们也可以像申明类一样的方式来申明委托.并调用它;

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Delegate
    {
        public class SayHello3
        {
            public delegate void SayHelloEventHandler(string _name);
            static void Main(string[] args)
            {
                SayHello3 s3 = new SayHello3();
                SayHelloEventHandler s1, s2;//定义了两个委托实例
                //为实例赋值
                s1 = s3.ChineseSayHello;
                s2 = s3.EnglishSayHello;
                s3.SayHello("张三", s1);
                s3.SayHello("张三", s2);
            }
            public void SayHello(string _name, SayHelloEventHandler sayHello)
            {
                sayHello(_name);
            }
            private void ChineseSayHello(string _name)
            {
                Console.WriteLine("你好:{0}", _name);
            }
            private void EnglishSayHello(string _name)
            {
                Console.WriteLine("hello:{0}", _name);
            }
        }
    }

    (2)、将多个方法绑定给同一个委托

    这是委托的一个特性:可以将多个方法赋给同一个委托,或者将多个方法绑定给同一个委托,当调用这个委托的时候,讲一次吊用该委托所绑定的方法;代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Delegate
    {
        class SayHello5
        {
            public delegate void SayHelloEventHandler(string _name);
            static void Main(string[] args) {
                SayHelloEventHandler sr1;
                SayHello5 s5 = new SayHello5();
                //如果需要给SayHelloEventHandler绑定多个方法,必须先给sr1赋初值,在做+=操作,否则编译器会报错
                sr1 = s5.EnglishSayHello;
                sr1 += s5.ChineseSayHello;
                sr1 -= s5.EnglishSayHello;
                sr1 += s5.EnglishSayHello;
                s5.SayHello("张三", sr1);
            }
            public void SayHello(string _name,SayHelloEventHandler sayHello) {
                sayHello(_name);
            }
            private void ChineseSayHello(string _name)
            {
                Console.WriteLine("你好:{0}", _name);
            }
    
            private void EnglishSayHello(string _name)
            {
                Console.WriteLine("hello:{0}", _name);
            }
        }
    }

    (3)上面代码中提到了当我们需要给一个委托绑定多个方法是,必须先给第一个赋初值在做+=运算,如果直接+=编译器则会报错。所以这个问题引申出第二种委托定义的方式,代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Delegate
    {
        class Thread4
        {
            public delegate void SayHelloEventHandler(string _name);
            static void Main(string[] args)
            {
                //前面说过委托也是一种类型,他可以向类一样的创建实例
                SayHelloEventHander sh = new SayHelloEventHander(ChineseSayHello);//创建了一个SayHelloEventHandler的实例,并给SayHelloEventHandler构造函数赋了初值ChineseSayHello
                //然后就可以做+=操作,做后续绑定工作
                sh += EnglishHello;
            }
    
            private static void ChineseSayHello(string name)
            {
                
            }
            private static void EnglishHello(string name)
            {
    
            }
    
        }
    }

    (4)利用面向对象的方法,封装代码,给上面的代码解耦

    分析上面的代码:发现SayHello()这个方法是不变的,那我们就把它封装起来,我们把SayHello的方法封装成SayHelloManager类,外部程序直接通过SayHelloManager类来访问并设置对应的SayHello()方法和参数。

    using System;
    namespace Delegate
    {
        //定义一个无返回值,但是有一个name参数的委托
        public delegate void SayHelloEventHandler(string _name);
        class SayHello6
        {
            static void Main(string[] args)
            {   
                //第一种方法
                SayHelloManger sm = new SayHelloManger();
                sm.SayHelloEventHandler = ChineseSayHello;
                sm.SayHelloEventHandler += EnglishSayHello;
                sm.SayHello("张三", sm.SayHelloEventHandler);
    
    
                //第二种调用方式
                SayHelloManger sm1 = new SayHelloManger("张三", ChineseSayHello);
                sm1.SayHello();
                SayHelloManger sm2 = new SayHelloManger("张三",EnglishSayHello);
                sm2.SayHello();
            }
            static void ChineseSayHello(string _name){
                Console.WriteLine("你好:{0}", _name);
              }
            static void EnglishSayHello(string _name){
                Console.WriteLine("Hello:{0}", _name);
              }
        }
        //定义一个SayHelloManager类,将所有SayHello()方法需要的参数设置成实例,并给外部调用
        public class SayHelloManger
        {
            public string _name;
            public SayHelloEventHandler _sayHelloEventHandler;
            public SayHelloEventHandler SayHelloEventHandler
            {
                get { return _sayHelloEventHandler; }
                set { _sayHelloEventHandler = value; }
            }
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
            public SayHelloManger()
            {
            }
            public SayHelloManger(string _name, SayHelloEventHandler handler)
            {
                this.SayHelloEventHandler = handler;
                this.Name = _name;
            }
            public void SayHello()
            {
                this.SayHelloEventHandler(Name);
            }
            public void SayHello(string _name,SayHelloEventHandler SayHello)
            {
                SayHello(_name);
            }
        }
    }

  • 相关阅读:
    Brain network involved in autonomic functions 与自主功能相关的大脑网络
    Brief summary of classical components of ERP 事件相关成分(ERP)经典成分小结
    ICA & Percentage Variance Account For (PVAF)
    数据处理中白化Whitening的作用图解分析
    Loadings vs eigenvectors in PCA 主成分分析(PCA)中的负荷和特征向量
    主成分分析(PCA)和独立成分分析(ICA)相关资料
    Sketch of heart and QRS complex 心脏及QRS波群简图
    Brain Network visulation in EEG 脑电网络可视化
    Phase Locking Value (PLV) 神经信号的锁相值
    ubuntu16.04下的一些基本操作笔记
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6347404.html
Copyright © 2011-2022 走看看