委托
委托:委托是一种安全地封装方法的引用类型,他是面向对象的、类型安全的和保险的,它可以代理一个或是多个方法,或是代码块执行,由于是引用类型,它保存的不是实际值,而是保存对存储在托管堆中的对象的引用,即对函数的引用。
构造委托对象的方法:
命名方法:使用命名方法构造的委托可以封装静态方法或实例方法(当然定义定义委托的时候不能用static修饰,静态方法不能调用实例化方法),命名方法代理的是方法。
public delegate void SampleDelegate(string message);
public static void SampleDelegateMethod(string message)
{
Console.WriteLine("SampleDelegateMethod:" + message);
}
SampleDelegate d1 =new SampleDelegate(SampleDelegateMethod);
//可以简写成
SampleDelegate d1 = SampleDelegateMethod;
d1("chentaihan");
匿名方法:匿名方法代理的是一段代码块,使用匿名方法,则不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。
SampleDelegate d2 = delegate(string message)
{
Console.WriteLine(message);
};
d2("chentaihan");
委托中的协变与逆变
协变实例如下
public class Animal
{
public Animal(string name)
{
this.Name = name;
}
protected string Name;
public virtual void ShowName()
{
Console.WriteLine("Animal:" + Name);
}
};
public class Cat : Animal
{
public Cat(string name) : base(name) { }
public override void ShowName()
{
Console.WriteLine("Cat:" + Name);
}
}
public delegate Animal DelegateAnimalXB(string name);
public class DelegateXB
{
public static Animal CreateAnimal(string name)
{
return new Animal(name);
}
public static Cat CreateCat(string name)
{
return new Cat(name);
}
public static void Test()
{
DelegateAnimalXB d1 = CreateAnimal;
d1("Animal").ShowName();//Animal:Animal
DelegateAnimalXB d2 = CreateCat;
d2("Cat").ShowName();//Cat:Cat
}
}
委托协变讲的是定义委托是返回类型的多态,我觉得重点根本不在委托,这其实还是一个类型转换的问题,定义委托时返回类型未Animal,你返回他的之类Cat,没有问题啊,编译器帮你隐式类型转换啊,就这样。
委托逆变实例如下:
public class MyEventArgs : EventArgs
{
public MyEventArgs(){}
}
public class DelegateNB
{
public delegate void Handler(EventArgs e);
public event Handler eventHandler;
public void Test(EventArgs e)
{
eventHandler(e);
}
}
static void Main(string[] args)
{
DelegateNB nb = new DelegateNB();
nb.eventHandler += new DelegateNB.Handler(Test);
nb.Test(new MyEventArgs());
Console.Read();
}
public static void Test(EventArgs e)
{
Console.WriteLine(e.ToString());
}
}
委托的逆变看上去实现了参数的多态,定义委托的时候,参数为EventArgs,而传进去的却是一个MyEventArgs,但是定义其他类型的参数,使用多态的方式传参却编译通过不了,只能是EventArgs及其之类,为什么是这样呢,俺也不知道,只知道事件代理的时候,定义委托的时候参数绝对是(object sender,EventArgs e),微软只用定义这一个事件,他就能委托很多类型的事件,如mouseup,mousedown,keyup等一堆类似的事件,正 因为定义委托的时候参数类型未EventArgs,所以你在写事件方法的时候参数为EventArgs或是相关的事件类(肯定也是EventArgs的之类)都是可以的。如文本框的KeyDown事件参数为KeyEventArgs,你用EventArgs是没有问题的,因为委托定义的时候参数就是EventArgs吗,当然用EventArgs没有会失去KeyEventArgs自带的属性和方法,反过来说如果我们不需要这些特有的属性和方法,用EventArgs会更好,杀鸡焉用宰牛刀。
泛型委托
泛型委托就会泛型跟委托的结合,根本不是什么新东西,只要你会泛型,会用委托,你就知道怎么使用泛型委托。泛型委托其实就是编译器动态的帮你定义一组委托,在你要用得时候才定义,不用就不定义,而且每种类型的委托只定义一次。泛型说白了就是编译器帮你写代码,当然使用他的确是减少了类型转换。
简单实例如下:
public class DelegateGeneric
{
public delegate void Del<T>(T item);
public static void f1(double i)
{
Console.WriteLine(i);
}
public static void Test()
{
Del<double> d1 = f1;
d1(1);//代理方法f1(double i),输出:1
}
}
委托不能重载,即委托名称相同,参数类型,个数不同。构造委托的时候,根本不管参数,当然也就不知道你要构造的是哪个委托。
委托不支持多态,正因为重载的存在导致委托不能支持多态。
public class A { }
public class B : A { }
public class DelegateDT
{
public delegate void DelegateFun(A a);
public static void DelegateA(A a)
{
Console.WriteLine("DelegateA");
}
public static void DelegateA(B a)
{
Console.WriteLine("DelegateB");
}
public static void Test()
{
DelegateFun d1 = DelegateA;
d1(new B());
}
}
这里其实调用的是方法DelegateA(A a),并不是DelegateA(B a),要是支持多态的话,他根本就不知道调用哪个方法,还是因为多态,你传进来一个对象B,正好有一个方法所需的参数是B的父类A,所以编译器自动将B隐式转换成A,然后调用方法DelegateA(A a),如果没有这个方法,编译是通不过的。多态不就是编译器帮我们寻找最合适的方法吗,如果没找到,就隐式转换,看有没有合适的方法,如果没有,编译出错。
作者:陈太汉
博客:http://www.cnblogs.com/hlxs/
本文转自啊汉博客园博客,原文链接:http://www.cnblogs.com/hlxs/archive/2011/11/26/2264496.html