C#委托
来源:互联网 发布:海岛导弹升级数据 编辑:程序博客网 时间:2024/05/01 18:21
可能很多初学者都听说过委托,但对于委托到底是什么就不得而知了。C#中用关键字delegate(英[ˈdeliɡit,ˈdelɪɡət])生命委托,为此我专门查了一下这个单词的音标和意思解释为:代表;托付。
那么究竟什么是委托呢?我们还是没有说明,我翻了一些书籍,对委托的解释:它是一种数据类型,和引用类型类似,不过和一般的类相比,委托的实例不是在堆中的数据,而是一个方法。委托类似于引用类型,和C++中的函数指针很相似,但是不同之处就在于,他不是存在于堆中的。正是有了委托我们才得以将函数打包成一个变量进行传递。这就是说,我们不止能够将数据作为参数传递,还可以将一个函数作为参数进行传递,这样就可以在需要的时候方便的进行控制的反转(Ioc,控制反转)。
说了那么多没有实际的例子还是理解不了,下面我们通过几个实例来看一下什么是委托:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegate
{
class Program
{
public delegate double DelegateOne(double d);//声明一个委托
public static double FunctionOne(double d)
{
return d * 2;
}
static void Main(string[] args)
{
DelegateOne dlgt = new DelegateOne(FunctionOne);//也可以直接DelegateOne dlgt = FunctionOne;
double d=dlgt(3);
Console.WriteLine(d);
Console.ReadKey();
}
}
}
这个例子比较简单,我们首先声明了一个委托DelegateOne,它有一个参数是double类型,返回值也是double类型的。然后定义了一个结构和它类似的方法FunctionOne,参数是double类型返回值也是double类型。在main方法中我们new了一个委托的实例,将FunctionOne传递给它,这就是说实例dlgt就有了FunctionOne的功能(但这里必须保证委托和方法的结构相同)。
下面我们看一下多路广播委托简称多播委托,也就是委托和方法的返回值是void类型。这是我们可以看到这种委托我们可以使用+=和-=来链入和去除多个委托。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegate
{
class MulticastDelegate
{
public delegate void DelegateOne(double d);//声明一个委托
public static void FunctionOne(double d)
{
Console.WriteLine(d * 2);
}
public static void FunctionTwo(double d)
{
Console.WriteLine(d * d);
}
static void Main(string[] args)
{
DelegateOne dlgt = new DelegateOne(FunctionOne);
dlgt += new DelegateOne(FunctionTwo);//这就是多播委托的好处
dlgt(3);
Console.ReadKey();
}
}
}
上面这个例子的运行结果是6 9,不是一个结果,而是相当于同时执行了两个方法,这也就是多播委托的特点。我们不仅可以+=一次还可以多次,而且还可以-=多次。我们对上述代码中的Main方法进行稍微的修改:
static void Main(string[] args)
{
DelegateOne dlgt = new DelegateOne(FunctionOne);
dlgt += new DelegateOne(FunctionTwo);//这就是多播委托的好处
dlgt(3);
Console.ReadKey();
dlgt -= new DelegateOne(FunctionTwo);
dlgt(3);
Console.Read();
}
这是的运行结果先是6 9,而后当你按了一个按键之后显示了6.说明什么问题呢,6 9的输出我们上面已经解释过了,因为我们链入了两个方法。后面一个是因为我们去点了一个方法FunctionTwo而只剩下FunctionOne,所以输出6.
多播委托,在教材上是说返回值必须是void,事实上通过实验我们会发现其实如果返回值不是void也可以,只不过这是我我们的就收结果是最后一个链入委托方法的返回值。
我们在前面提到了委托不是存放在堆中的,而是作为一个方法,下面我们具体看看是不是这样:
我们知道,如果是存到了堆中,例如类A和类B(类肯定是在堆中存放的),如果我们另A a=new A(); B b;b=a;这是我们修改b,就可以影响到a。换句话说如果委托也是这样,我们也可以看到这样的结果,那么是不是呢?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegate
{
class DelegateNotRef
{
public delegate string DelegateOne();
static void Main(string[] args)
{
int x = 3;
DelegateOne dlgt = new DelegateOne(x.ToString);
Console.WriteLine(dlgt());
x = 4;
Console.WriteLine(dlgt());
Console.WriteLine(x.ToString());
Console.Read();
}
}
}
可以看到,我们输出为3 3 4,而不是3 4 4,说明我们在修改x=4后,委托中的东西并没有随之修改,也就说明了委托不是在堆中存储的。
接下来我们进一步看看泛型委托:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Delegate
{
class GnericDelegate
{
public delegate string DelegateOne(T t,S s);
public static string FunctionOne(string s, int i)
{
return s + i.ToString();
}
public static string FunctionTwo(string s1, string s2)
{
return s1 + s2;
}
static void Main(string[] args)
{
DelegateOne dlgt = new DelegateOne(FunctionOne);
Console.WriteLine(dlgt("ab", 42));
DelegateOne dlgt2 = new DelegateOne(FunctionTwo);
Console.WriteLine(dlgt2("abc","def"));
Console.Read();
}
}
}
很简单,和我们的其他类型的泛型没有多大的差别,这里就不再赘余!
- C#委托-委托概述
- C#委托
- C#委托
- C#委托
- c#委托
- C# 委托
- C#委托
- C# 委托
- c#委托
- C#委托
- c#委托
- C#委托
- C# - 委托
- C#委托
- C#委托
- C#委托
- C# 委托
- c#委托
- javascript 放大镜(学习至CSDN论坛)
- c# 语音卡控制--语音卡实现电话录音
- 抽象类与接口的区别【转】
- 我是主考官:他为什么没有被录取
- "此页的状态信息无效,可能已损坏"的原因和解决方法
- C#委托
- 轻松实现SQL Server与Access、Excel数据表间的导入导出
- 第一次写blog
- C语言内存分布
- Java中一些关于日期、日期格式、日期的解析和日期的计算
- Java开源IDE
- IE6中select标签的option不能disabled的解决方案
- 导出excel
- 专家访谈:谈谈虚拟化的价值