关于委托的实现
为了实现方法的参数化,学者们提出了委托的概念。
委托是一种引用方法的类型,即委托是方法的引用,一旦为委托分配了方法,委托将与该方法具有完全相同的行为;另外,.NET中为了简化委托方法的定义,提出了匿名方法的概念。本篇技术内容将对委托和匿名方法进行讲解。
委托
C#中的委托(Delegate)是一种引用类型,该引用类型与其他引用类型有所不同。在委托对象的引用中存放的不是对数据的引用,而是存放对方法的引用,即在委托的内部包含一个指向某个方 法的指针。通过使用委托把方法的引用封装在委托对象中,然后将委托对象传递给调用引用方法的代码。委托类型的声明语法格式如下:
修饰符 delegate 返回类型 委托名称 (参数列表)
修饰符dleate返回类型委托名称(参数列表)其中,修饰符是可选项;返回类型、关键fegae和凌托名称是必需项:列表用来指定委托所匹配的方法的参数列表,所以是可选项。一个 与委托类型相匹配的方法必须满足以下两个条件。
这二者具有相同的签名, 即具有相同的参数目,并且类型相同,顺序相同,参数的修饰符也相同。
这二者具有相同的返回值类型。委托是方法的类型安全的引用,之所以说委托是安全的,是因为委托和其他所有的C#成员一样,是一一种数据类型,并且任何委托对象都是System.Delegate的某个派生类的一一个对象 ,委托的类结构如图一所示。
从图一的结构图中可以看出,任何自定义委托类型都继承自System. Delegate类型,并且该类型封装了许多委托的特性和方法。下面通过一个具体的例子来说明委托的定义及应用。
例:创建一个控制台应用程序,首先定义一个实例方法Add,该方法将作为自定义委托类型MyDelegate 的匹配方法;然后在控制台应用程序的默认类Program中定义一个委托类型MyDelegate ,接着在应用程序的入口方法Main中创建该委托类型的实例md,并绑定到Add方法。代码如下:
public classTestClass { public int Add(int x,int y) { Return x+y; } } Class Program { Public delefate int MyDelegate(int x,int y); Static void Main(string[] args) { TestClass tc = new TestClass(); MyDelegate md = tc.Add; Int intSum = md(2 , 3); Console.WriteLine(“运算结果是:”+intSum.ToString()); Console.Read(); } } |
上面代码中的MyDelegate自定义委托类型继承自System.MulticastDelegate,并且该自定义委托类型包含一个名为Invoke的方法,该方法接受两个整型参数并返回一个整数值,由此可见,Invoke方法的参数及返回值类型与Add方法完全相同。实际上程序在进行委托调用时就是调用了Invoke方法,所以上面的委托调用完全可以写成下面的形式:
Int intSum = md.Invoke(2 , 3); //委托的调用 |
其实,上面的这种形式更有利于初学者的理解,上面代码的运算结构为:“运算结果是:5”。
关于virtual虚方法
在默认情况下方法、属性都是非虚拟的,而被virtual关键字修饰的父类实例方法被称为虚方法,就是说明需要再派生类中的重写、修改。被virtual关键字修饰的方法,必须有方法体,不能像抽象方法那样简写,虚方法表现如下:
Virtual public void Add() { Console.WriteLine(“我是虚方法”); } |
如果要重写方法,必须使用override关键字声明,override表示覆盖(重写),派生类的方法签名和返回值类型必须要和父类相同,相同时才说明是重写。例如下:
Public override void Add() { Console.WriteLine(“我是虚方法重写”); } |
如果父类的某个实例方法被virtual关键字修饰,但是派生类重写的时候没有使用override关键字修饰,此时不报错,但会发出警报。如果父类的某个实例方法被virtual修饰,而派生类并没重写,只继承了,那么通过调用派生类的输出结果就是父类的,这就让关键字override修饰得毫无作用。
Virtual关键字不能和static同用,只能据实际情况选其一,这是因为virtual修饰后就让继承重写的,而被static关键字修饰的静态方法是不能继承的,如下是一个错误例子:
static public virtual void Add() { Console.WritLine(“本想重写,实现错误”) } |
同样,virtual关键字也不能同private关键字同用,因为virtual关键字是继承重写的,而private是私有的,是不能继承的,也就是,private关键字不能用于声明虚方法。如下是错误例子:
Private virtual voidAdd() { Console.WriteLine(“错误用法”); } |