引言:

对于一些刚接触C# 不久的朋友可能会对C#中一些基本特性理解的不是很深,然而这些知识也是面试时面试官经常会问到的问题,所以我觉得有必要和一些接触C#不久的朋友分享下关于C#基础知识的文章,所以有了这个系列,希望通过这个系列让朋友对C#的基础知识理解能够更进一步。然而委托又是C#基础知识中比较重要的一点,基本上后面的特性都和委托有点关系,所以这里就和大家先说说委托,为什么我们需要委托。

一、C#委托是什么的?

在正式介绍委托之前,我想下看看生活中委托的例子——生活中,如果如果我们需要打官司,在法庭上是由律师为我们辩护的,然而律师真真执行的是当事人的陈词,这时候律师就是一个委托对象,当事人委托律师这个对象去帮自己辩护。这就是我们生活中委托的例子的。然而C#中委托的概念也就好比律师对象(从中可以得出委托是一个类,,因为只有类才有对象的概念,从而也体现了C#是面向对象的语言)。

介绍完生活中委托是个什么后,现在就看看C#中的委托怎样和生活中的对象联系起来的,C#中的委托相当于C++中的函数指针(如果之前学过C++就知道函数指针是个什么概念的了),函数指针是用指针获取一个函数的入口地址,然后通过这个指针来实现对函数的操作。C#中的委托相当于C++中的函数指针,也就说两者是有区别的:委托是面向对象的,类型安全的,是引用类型(开始就说了委托是个类),所以在使用委托时首先要 定义——>声明——>实例化——>作为参数传递给方法——>使用委托。下面就具体看下如何使用委托的:

一、定义:delegate void Mydelegate(type1 para1,type2 para2);

二、声明: Mydelegate d;

三、实例化:d =new Mydelegate(obj.InstanceMethod);(把一个方法传递给委托的构造器),前面三步就好比构造一个律师对象,方法InstanceMethod好比是当事人

四、作为参数传递给方法:MyMethod(d);(委托实现把方法作为参数传入到另一个方法,委托就是一个包装方法的对象)

五、在方法中使用委托。MyMethod方法好比是法官,MyMethod方法先调用委托,委托在调用方法InstanceMethod,这个过程就如法官向律师问话,然后律师之前肯定向当事人了解了案件的情况。C#委托中好比是律师,真真诉说案情的是当事人(真真被调用的是实例方法InstanceMethod)

MyMethod方法的定义如下:

[csharp] 

private void MyMethod(Mydelegate mydelegate) 

 



    // 使用委托  

    mydelegat(arg1,arg2); 

 

}

private void MyMethod(Mydelegate mydelegate)

{

    // 使用委托

    mydelegat(arg1,arg2);

}

二、C#中为什么要使用委托的?

相信经过上面的介绍,大家应该对委托不再陌生了吧,然而我们为什么需要委托的,好好地为什么要实例化中间这个对象的,为什么不直接在MyMethod方法里面调用InstanceMethod方法的,这样不是自找麻烦的吗?为了大家可以更好的明白为什么要使用委托,下面通过一个Window Form的 ”文字抄写员“ 程序要解释下为什么。

程序实现的功能是:在下方文本框输入文字,勾选“书写到”组合框中的“文本区1”或“文本区2”复选框后点击“开始”按钮,程序会自动将文本框中的文字”抄写“到对应的文本区中去。程序界面如下:

传统的实现代码为:

[csharp] 

namespace 文字抄写员 



    public partial class Form1 : Form 

    { 

        public Form1() 

        { 

            InitializeComponent(); 

        } 

 

        private void button1_Click(object sender, EventArgs e) 

        { 

            if (checkBox1.Checked == true) 

            { 

                textBox1.Clear(); 

                textBox1.Refresh(); 

                // 调用方法WriteRichTextBox1想文本区1写入文字  

                this.WriteTextBox1(); 

                textBox3.Focus(); 

                textBox3.SelectAll(); 

            } 

            if (checkBox2.Checked == true) 

            { 

                textBox2.Clear(); 

                textBox2.Refresh(); 

                // 调用方法WriteRichTextBox2想文本区2写入文字  

                this.WriteTextBox2(); 

                textBox3.Focus(); 

                textBox3.SelectAll(); 

            } 

        } 

 

        private void WriteTextBox1() 

        { 

            string data = textBox3.Text; 

            for (int i = 0; i < data.Length; i++) 

            { 

                textBox1.AppendText(data[i].ToString()); 

                //间歇延时  

                DateTime now = DateTime.Now; 

                while(now.AddSeconds(1)>DateTime.Now) 

                { } 

            } 

        } 

 

        private void WriteTextBox2() 

        { 

            string data = textBox3.Text; 

            for (int i = 0; i < data.Length; i++) 

            { 

                textBox2.AppendText(data[i].ToString()); 

                //间歇延时  

                DateTime now = DateTime.Now; 

                while (now.AddSeconds(1) > DateTime.Now) 

                {  } 

            } 

        } 

    } 

}

namespace 文字抄写员

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

private void button1_Click(object sender, EventArgs e)

        {

            if (checkBox1.Checked == true)

            {

                textBox1.Clear();

                textBox1.Refresh();

                // 调用方法WriteRichTextBox1想文本区1写入文字

                this.WriteTextBox1();

                textBox3.Focus();

                textBox3.SelectAll();

            }

            if (checkBox2.Checked == true)

            {

                textBox2.Clear();

                textBox2.Refresh();

                // 调用方法WriteRichTextBox2想文本区2写入文字

                this.WriteTextBox2();

                textBox3.Focus();

                textBox3.SelectAll();

            }

        }

private void WriteTextBox1()

        {

            string data = textBox3.Text;

            for (int i = 0; i < data.Length; i++)

            {

                textBox1.AppendText(data[i].ToString());

                //间歇延时

                DateTime now = DateTime.Now;

                while(now.AddSeconds(1)>DateTime.Now)

                { }

            }

        }

private void WriteTextBox2()

        {

            string data = textBox3.Text;

            for (int i = 0; i < data.Length; i++)

            {

                textBox2.AppendText(data[i].ToString());

                //间歇延时

                DateTime now = DateTime.Now;

                while (now.AddSeconds(1) > DateTime.Now)

                {  }

            }

        }

    }

}然而我们从代码中会发现WriteTextBox1()方法和WriteTextBox2()只有一行代码不一样的( textBox1.AppendText(data[i].ToString()); 和 textBox2.AppendText(data[i].ToString());),其他都完全一样,而这条语句的差别就在于向其中写入文本的控件对象不一样,一个是TextBox1和TextBox2,现在这样代码是实现了功能,带式我们试想下,如果要实现一个写入的文本框不止2个,而是好几十个甚至更多,那么不久要写出同样多数量的用于写入文本区的方法了吗?这样就不得不写重复的代码,导致代码的可读性就差,这样写代码也就是面向过程的一个编程方式,因为函数是对操作过程的一个封装,要解决这个问题,自然我们就想到面向对象
编程,此时我们就会想到把变化的部分封装起来,然后再把封装的对象作为一个对象传递给方法的参数的(这个思想也是一种设计模式——策略模式,关于设计模式系列会在后面也会给出的),下面就利用委托来重新实现下这个程序:

[csharp] 

namespace 文字抄写员 



    public partial class Form1 : Form 

    { 

        // 定义委托  

        private delegate void WriteTextBox(char ch); 

        // 声明委托  

        private WriteTextBox writeTextBox; 

 

        public Form1() 

        { 

            InitializeComponent(); 

        } 

 

        private void button1_Click(object sender, EventArgs e) 

        { 

            if (checkBox1.Checked == true) 

            { 

                textBox1.Clear(); 

                textBox1.Refresh(); 

                // 实例化委托  

                writeTextBox = new WriteTextBox(WriteTextBox1); 

                // 作为参数  

                WriteText(writeTextBox); 

 

                textBox3.Focus(); 

                textBox3.SelectAll(); 

            } 

            if (checkBox2.Checked == true) 

            { 

                textBox2.Clear(); 

                textBox2.Refresh(); 

                // 实例化委托  

                writeTextBox = new WriteTextBox(WriteTextBox2); 

                // 作为参数  

                WriteText(writeTextBox); 

 

                textBox3.Focus(); 

                textBox3.SelectAll(); 

            } 

        } 

 

 

        private void WriteText(WriteTextBox writetextbox) 

        { 

            string data = textBox3.Text; 

            for (int i = 0; i < data.Length; i++) 

            { 

                // 使用委托  

                writetextbox(data[i]); 

                DateTime now = DateTime.Now; 

                while (now.AddSeconds(1) > DateTime.Now) 

                { } 

            } 

        } 

 

        private void WriteTextBox1(char ch) 

        { 

            textBox1.AppendText(ch.ToString()); 

        } 

        private void WriteTextBox2(char ch) 

        { 

            textBox2.AppendText(ch.ToString()); 

        } 

    } 

}

namespace 文字抄写员

{

    public partial class Form1 : Form

    {

        // 定义委托

        private delegate void WriteTextBox(char ch);

        // 声明委托

        private WriteTextBox writeTextBox;

public Form1()

        {

            InitializeComponent();

        }

private void button1_Click(object sender, EventArgs e)

        {

            if (checkBox1.Checked == true)

            {

                textBox1.Clear();

                textBox1.Refresh();

                // 实例化委托

                writeTextBox = new WriteTextBox(WriteTextBox1);

                // 作为参数

                WriteText(writeTextBox);

textBox3.Focus();

                textBox3.SelectAll();

            }

            if (checkBox2.Checked == true)

            {

                textBox2.Clear();

                textBox2.Refresh();

                // 实例化委托

                writeTextBox = new WriteTextBox(WriteTextBox2);

                // 作为参数

                WriteText(writeTextBox);

textBox3.Focus();

                textBox3.SelectAll();

            }

        }

private void WriteText(WriteTextBox writetextbox)

        {

            string data = textBox3.Text;

            for (int i = 0; i < data.Length; i++)

            {

                // 使用委托

                writetextbox(data[i]);

                DateTime now = DateTime.Now;

                while (now.AddSeconds(1) > DateTime.Now)

                { }

            }

        }

private void WriteTextBox1(char ch)

        {

            textBox1.AppendText(ch.ToString());

        }

        private void WriteTextBox2(char ch)

        {

            textBox2.AppendText(ch.ToString());

        }

    }

}

引入委托后实现的代码中,我们通过WriteText方法来向文本区写入内容,它所执行的只是抽象的”写文本“操作,至于究竟像那个文本框写入文字,对于编写WriteText方法的程序来说是不知道,委托writeTextBox就像一个接口一样(面向对象设计原则中有一个很重要的原则就是——针对接口编程,不针对实现编程),屏蔽了操作对象的差别(方法到底是想向文本区1写入文本还是像文本区2写入文本,现在我方法里面不需要去关心,我只需要集中在实现”书写文本”这个操作,而不必纠结操作对象的选择)。

三、委托的作用到底是什么?——委托总结陈词

相信通过上面两部分大家也明白了委托是个什么东西以及C#中为什么要引入委托这个概念。现在就总结下引入委托后到底作用在那里的? 从上面的委托代码中可以发现,引入委托后,编程人员可以把方法的引用封装在委托对象中(把过程的调用转化为对象的调用,充分体现了委托加强了面向对象编程的思想。),然后把委托对象传递给需要引用方法的代码,这样在编译的过程中我们并不知道调用了哪个方法,这样一来,C#引入委托机制后,使得方法声明和方法实现的分离,充分体现了面向对象的编程思想。

委托对自己的总结:

我是一个特殊的类,我定义了方法的类型,(就像int定义了数字类型一样,当用一个方法实例化委托对象时,这个委托就代表一个方法,这个方法的类型就是委托类型),我可以将方法当做另一个方法的参数来进行传递,使得程序更容易扩展

四、小结

写到这里本专题介绍的内容也结束了,在本专题中有些地方提到了一些设计模式的知识的,如果有朋友对设计模式还没有开始学习的话,建议大家都去学习下的,并且我也会在后面的系列中向大家分享下我的理解的。对于本系列的下一专题将和大家分享下我理解的事件到底是个什么样的概念。最后希望本专题可以让大家进一步理解委托。

C#深入解析委托——C#中为什么要引入委托的更多相关文章

  1. [C# 基础知识系列]专题一:深入解析委托——C#中为什么要引入委托

    转自http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html 引言: 对于一些刚接触C# 不久的朋友可能会对C#中一些基本特性理解的不 ...

  2. 解析C#类中的构造函数

    <解析C#类中的构造函数> 一.  C#中的构造函数概述: C#中类包含数据成员和函数成员.函数成员提供了操作类中数据的某些功能,包括方法.属性.构造器和终结器.运算符和索引器. 构造函数 ...

  3. XML:使用DOM技术解析xML文件中的城市,实现select级联选择

    中国的城市xml格式:cities.xml <?xml version="1.0" encoding="utf-8"?> <china> ...

  4. 委托学习笔记后续:泛型委托及委托中所涉及到匿名方法、Lambda表达式

    引言: 最初学习c#时,感觉委托.事件这块很难,其中在学习的过程中还写了一篇学习笔记:委托.事件学习笔记.今天重新温故委托.事件,并且把最近学习到和委托相关的匿名方法.Lambda表达式及泛型委托记录 ...

  5. 解析iOS开发中的FirstResponder第一响应对象

    1. UIResonder 对于C#里所有的控件(例如TextBox),都继承于Control类.而Control类的继承关系如下: 代码如下: System.Object System.Marsha ...

  6. 《C#高级编程》学习笔记------C#中的事件和委托

    本文转载自张子阳 目录 委托的作用 将方法绑定到委托 事件的来由 Observer设计模式 .Net Framework中的委托与事件   引言 委托 和 事件在 .Net Framework中的应用 ...

  7. c#中的delegate(委托)和event(事件)

    c#中的delegate(委托)和event(事件) 一.delegate是什么东西? 完全可以把delegate理解成C中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能 ...

  8. ios中关于delegate(委托)的使用心得

    ios中关于delegate(委托)的使用心得 分类: iOS开发2012-05-15 10:54 34793人阅读 评论(9) 收藏 举报 iosuiviewtimerinterfaceprinti ...

  9. parse_str() 函数把查询字符串解析到变量中。

    定义和用法 parse_str() 函数把查询字符串解析到变量中. 注释:如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量. 注释:php.ini 文件中的 magic_quo ...

随机推荐

  1. js 时间戳和日期互转

    // 获取当前时间戳(以s为单位) var timestamp = Date.parse(new Date()); timestamp = timestamp / 1000; //当前时间戳为:140 ...

  2. Hi3516CV300 sample -> region

  3. mysql 的 docker 镜像使用

    mysql 的 docker 镜像使用: 下载镜像: docker pull mysql:8.0.14 运行容器: docker run -it -e MYSQL_ROOT_PASSWORD=mypw ...

  4. xcode 添加target

  5. ML平台_Paddle参考

    PaddlePaddle源自于 2013 年百度深度学习实验室创建的 “Paddle”.当时的深度学习框架大多只支持单 GPU 运算,对于百度这样需要对大规模数据进行处理的机构,这显然远远不够,极大拖 ...

  6. 弄清SDI显示工程中的每一个信号,每一个逻辑

    弄清SDI显示工程中的每一个信号,每一个逻辑 1. FIFO外部逻辑控制 FIFO的读和写在不同的时钟域,所以读和写的控制逻辑应当分开写在不同的两个always块语句中. 2.播出端复位信号的产生 : ...

  7. ArrayBlcokingQueue,LinkedBlockingQueue与Disruptor三种队列对比与分析

    一.基本介绍 ArrayBlcokingQueue,LinkedBlockingQueue是jdk中内置的阻塞队列,网上对它们的分析已经很多,主要有以下几点: 1.底层实现机制不同,ArrayBlco ...

  8. 黄聪:bootstrapValidator验证成功,按钮变灰却无法提交的问题

    对于这个坑真心无语! 主要问题是按钮的id和name不能为submit! 改成别的就好了!

  9. sublime 最近用的有点卡

    index_files:false,

  10. Linux From Scratch [3]

    1. 为了编译glibc,我们需要kernel header. make mrproper # clean kernel tree make INSTALL_HDR_PATH=dest headers ...