在这里补充两个对委托运用得比较少的示例:
一、将委托作为参数传递,然后再调用;
二、使用委托调用内部类中的方法;
示例一:委托作为参数
委托作为参数.cs
using
System;
using System.Collections.Generic;
using System.Text;
namespace 委托作为参数
{
class 计算器
{
public delegate int delCalculate( int a, int b);
// 将委托作为参数
public void Fun( int a, int b, delCalculate cal)
{
if (cal != null )
{
Console.WriteLine(cal(a,b));
}
}
// 加法
public int Add( int a, int b)
{
return a + b;
}
// 减法
public int Reduce( int a, int b)
{
return a - b;
}
}
class Run
{
static void Main( string [] args)
{
计算器 js = new 计算器();
// 调用加法
计算器.delCalculate d1 = new 计算器.delCalculate(js.Add);
js.Fun( 20 , 10 , d1); // 将委托作为参数
// 调用减法
js.Fun( 20 , 10 , new 计算器.delCalculate(js.Reduce));
}
}
}
using System.Collections.Generic;
using System.Text;
namespace 委托作为参数
{
class 计算器
{
public delegate int delCalculate( int a, int b);
// 将委托作为参数
public void Fun( int a, int b, delCalculate cal)
{
if (cal != null )
{
Console.WriteLine(cal(a,b));
}
}
// 加法
public int Add( int a, int b)
{
return a + b;
}
// 减法
public int Reduce( int a, int b)
{
return a - b;
}
}
class Run
{
static void Main( string [] args)
{
计算器 js = new 计算器();
// 调用加法
计算器.delCalculate d1 = new 计算器.delCalculate(js.Add);
js.Fun( 20 , 10 , d1); // 将委托作为参数
// 调用减法
js.Fun( 20 , 10 , new 计算器.delCalculate(js.Reduce));
}
}
}
示例二:委托调用内部类的方法
委托调用内部类的方法.cs
using
System;
using System.Collections.Generic;
using System.Text;
namespace 委托调用内部类的方法
{
class Person
{
public delegate void myDelegate( string str);
public void Fun( string str)
{
Console.WriteLine(str);
}
// 内部类的调用
public class InnerClass
{
public void SubFun( string str)
{
Console.WriteLine(str);
}
}
}
class Program
{
static void Main( string [] args)
{
Person p = new Person();
// 内部委托的实例化(用类名调用)
Person.myDelegate pm1 = new Person.myDelegate(p.Fun);
pm1( " 内部委托调用的方法 " );
// 内部类 InnerClass
Person.InnerClass pc = new Person.InnerClass();
Person.myDelegate pm2 = new Person.myDelegate(pc.SubFun);
pm2( " 内部委托调用内部类的方法 " );
}
}
}
using System.Collections.Generic;
using System.Text;
namespace 委托调用内部类的方法
{
class Person
{
public delegate void myDelegate( string str);
public void Fun( string str)
{
Console.WriteLine(str);
}
// 内部类的调用
public class InnerClass
{
public void SubFun( string str)
{
Console.WriteLine(str);
}
}
}
class Program
{
static void Main( string [] args)
{
Person p = new Person();
// 内部委托的实例化(用类名调用)
Person.myDelegate pm1 = new Person.myDelegate(p.Fun);
pm1( " 内部委托调用的方法 " );
// 内部类 InnerClass
Person.InnerClass pc = new Person.InnerClass();
Person.myDelegate pm2 = new Person.myDelegate(pc.SubFun);
pm2( " 内部委托调用内部类的方法 " );
}
}
}
事件
由于MSDN含混不清的误导,很多人会认为:事件就是一种受限的委托。但实际上不是!
事件与委托 的关系好比 字段与属性 的关系。
事件实际上是一种委托属性,只不过这个属性重载的不是赋值运算符,而是+=和-=运算符。
对于一个属性而言,对它的赋值和取值运算会被转换为两个方法的调用。
例如:obj.A 这个属性
obj.A = "aaa"; 将调用 set 访问器: set { _a = value; }
string a = obj.A; 将调用 get 访问器: get { return _a; }
而事件也是一样,假设有一个事件obj.E,则下面的表达式也等同于后面的形式:
obj.E += d; obj.add_E( d )
obj.E -= d; obj.remove_E( d )
事件与属性的共同点:
事件也可以被继承;
事件也可以被重写;
事件也可以是虚的或者抽象的(表现在add和remove方法是抽象的或者虚的);
理论上,事件的add和remove方法也可以有不同的访问权限。
事件与属性的不同点:
属性是必须实现的,事件则不必(或者说,事件是最早出现的自动属性);
与自动属性一样,事件也会创建一个字段来保存对应的委托实例,而这个字段与事件同名且是私有。在C#中,你可以访问到这个字段,因为它真的就是一个字段。
换言之,在C#中写代码时,如果是在类的内部使用事件,其实就是引用那个自动生成的私有字段(委托字段)。
而在类的外部使用事件,是不同于在类的内部使用事件(因为这个字段是私有的,所以在类的外部也就访问不到)。
event 本质上所做的工作应该还是通过 delegate 来实现的,或者至少原理相同。event 关键字只不过是让CLR给所定义的 delegate 对象进行一个封装。
event 是通过对 delegate 的限制来封装一部分本来就不应该暴露在外的行为,从而更符合面向对象的思想(封装的原则)。
附加:
1、事件其实是由三个方法add、remove和raise组成的。但C#编译器总是不会生成raise方法。
2、自动事件不同的编译器实现是不同的,例如VB的编译器生成的私有字段是(事件名)Event。
3、Web开发中的Control也是事件驱动的。
本文转自钢钢博客园博客,原文链接:http://www.cnblogs.com/xugang/archive/2010/04/28/1723254.html,如需转载请自行联系原作者