一、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方法的定义如下:

private void MyMethod(Mydelegate mydelegate)

{
// 使用委托
mydelegat(arg1,arg2); }

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

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

传统的实现代码为:

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 = ; i < data.Length; i++)
{
textBox1.AppendText(data[i].ToString());
//间歇延时
DateTime now = DateTime.Now;
while(now.AddSeconds()>DateTime.Now)
{ }
}
} private void WriteTextBox2()
{
string data = textBox3.Text;
for (int i = ; i < data.Length; i++)
{
textBox2.AppendText(data[i].ToString());
//间歇延时
DateTime now = DateTime.Now;
while (now.AddSeconds() > DateTime.Now)
{ }
}
}
}
}

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

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 = ; i < data.Length; i++)
{
// 使用委托
writetextbox(data[i]);
DateTime now = DateTime.Now;
while (now.AddSeconds() > 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定义了数字类型一样,当用一个方法实例化委托对象时,这个委托就代表一个方法,这个方法的类型就是委托类型),我可以将方法当做另一个方法的参数来进行传递,使得程序更容易扩展

本文转载自  http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html

面试问题 ---C#中的委托的更多相关文章

  1. 彻底搞清楚c#中的委托和事件

    一.什么是委托呢? 听着名字挺抽象,确实不好理解.面试官最喜欢考察这个,而且更喜欢问:“委托和事件有何异同?”.如果对一些知识点没有想明白,那么很容易被绕进去.研究任何事物,我们不妨从它的定义开始,委 ...

  2. C# 中的委托和事件

    觉得这篇文章写的非常好,大神之作,由简入繁,对我这种初学者来说帮忙很大,特此留存下. 摘自:http://tracefact.net/CSharp-Programming/Delegates-and- ...

  3. Objective-C中的委托(代理)模式

    我个人更喜欢把委托(Delegate)模式称为代理(Proxy)模式.还是那句话,第一次接触代理模式是在Java中接触的,在Java中实现代理模式和接口是少不了的.当时学习Spring的时候用到了接口 ...

  4. C# 中的委托和事件(转)

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  5. C# 中的委托和事件(转载)

    引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...

  6. 【转】C# 中的委托和事件

    阅读目录 C# 中的委托和事件 引言 将方法作为方法的参数 将方法绑定到委托 事件的由来 事件和委托的编译代码 委托.事件与Observer设计模式 .Net Framework中的委托与事件 总结 ...

  7. 第3章 C#中的委托和事件

    .NET框架中的委托和事件 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  8. 分分钟用上C#中的委托和事件之窗体篇

    上次以鸿门宴的例子写了一篇名为<分分钟用上C#中的委托和事件>的博文,旨在帮助C#初学者迈过委托和事件这道坎,能够用最快的速度掌握如何使用它们.如果觉得意犹未尽,或者仍然不知如何在实际应用 ...

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

    本文转载自张子阳 目录 为什么要使用事件而不是委托变量? 为什么委托定义的返回值通常都为void? 如何让事件只允许一个客户订阅?(事件访问器) 获得多个返回值与异常处理 委托中订阅者方法超时的处理 ...

随机推荐

  1. mysql双机热备+heartbeat集群+自动故障转移

    环境说明:本环境由两台mysql 数据库和heartbeat 组成,一台的ip 为 192.168.10.197,一台为192.168.10.198,对外提供服务的vip 为192.168.10.20 ...

  2. 九度OJ 1026:又一版 A+B (进制转换)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:11412 解决:3086 题目描述: 输入两个不超过整型定义的非负10进制整数A和B(<=231-1),输出A+B的m (1 < ...

  3. new 和 make 均是用于分配内存

    the-way-to-go_ZH_CN/06.5.md at master · Unknwon/the-way-to-go_ZH_CN https://github.com/Unknwon/the-w ...

  4. TVirtualStringTree的Minimal例子学习

    预步骤第一步,定义数据结构type PMyRec = ^TMyRec; TMyRec = record Caption: WideString; end;预步骤第二步,规定取得节点数据时候的大小pro ...

  5. 列举Python常用数据类型并尽量多的写出其中的方法

    #1 把字符串的第一个字符大写 string.capitalize() #2 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串 string.center(width) #3 返回 ...

  6. 在linux通过源码编译安装redis详细步骤

    1.下载源码包 [root@localhost opt]# wget http://download.redis.io/releases/redis-4.0.10.tar.gz 2.解压缩redis ...

  7. 转换(旋转)transform

    div { transform:rotate(180deg); -ms-transform:rotate(180deg); /* IE 9 */ -moz-transform:rotate(180de ...

  8. 在pycharm中执行脚本没有报错但输出显示Redirection is not supported.

    没有新式语法错误,但是输出显示Redirection is not supported.(不支持重定向) 在stockflow中找到是因为从IDE中运行脚本的原因,比如pycharm,所有IDE都提供 ...

  9. jQuery 的文档操作

    在 js 中也有DOM操作,也可以进行 增删改查 ,但是通过 js 的DOM操作会发现,我的天哪,代码好多.但是 jQuery的文档操作就少了很多. js 中 DOM 的示例 : var box = ...

  10. [egret+pomelo]实时游戏杂记(2)

    [egret+pomelo]学习笔记(1) [egret+pomelo]学习笔记(2) [egret+pomelo]学习笔记(3) pomelo pomelo服务端介绍(game-server/con ...