委托的概念[转载]
委托是一种数据结构,它引用静态方法或引用类实例及该类的实例方法。 ————MSDN
delegate 是一种可用于封装命名或匿名方法的引用类型。 委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。 ————MSDN
委托四要素:
1、The delegate type needs to be declared. 声明
2、There must be a method containing the code to execute.可执行方法
3、A delegate instance must be created. 实例化
4、The delegate instance must be invoked.实例调用
实例化(MSDN上说的是声明,感觉更应该叫做实例化)委托的可使用命名方法、匿名方法和Lambda 表达式。
顾名思义,命名方法声明委托如下:
命名方法
delegate void StringProcessor(string input);
class Person
{
string name;
public Person(string name)
{
this.name = name;
}
public void Say(string message)
{
Console.WriteLine("{0} say:{1}", name, message);
}
public void Call(string message)
{
Console.WriteLine("{0}", message);
}
class Background
{
public static void Note(string note)
{
Console.WriteLine("({0})", note);
}
}
class Program
{
static void Main(string[] args)
{
Person jon = new Person(name: "Jon");
Person tom = new Person("Tom");
StringProcessor jonsVoice, tomsVoice, background;
jonsVoice = new StringProcessor(jon.Say);
tomsVoice = new StringProcessor(tom.Say);
background = new StringProcessor(Background.Note);
}
}
在使用命名方法实例化时,委托对应的方法的参数和返回值应与委托类型一致的定义一致。
匿名方法实例化:
采用匿名方法实例化可在实例化委托之前不需定义委托的实现对象,如:
jonsVoice += delegate(string message) { Console.WriteLine(“Anonymous"+message); };
jonsVoice += delegate{ Console.WriteLine(“I don't have parameter!"); };
采用Lambda方式实例化则更加简洁
jonsVoice += message => Console.WriteLine("Lambda:"+message);
但是采用Lambda方式实例化不能忽略参数列表。
委托调用
jonsVoice(input: "Hello,son");
tomsVoice.Invoke("Hello,Daddy!");
background("An airplane flies past");
运行结果如下:
有返回值的委托:
在有返回值的委托中,当委托调用的时候,返回的是委托列表中最后一个方法的返回值:
代码
delegate string StringProcessor(string input);
class Person
{
string name;
public Person(string name)
{
this.name = name;
}
public string Say(string message)
{
//Console.WriteLine("{0} say:{1}", name, message);
return message;
}
public string Call(string message)
{
//Console.WriteLine("{0}", message);
return message;
}
class Background
{
public static string Note(string note)
{
//Console.WriteLine("({0})", note);
return note;
}
}
class Program
{
//static event StringProcessor SayEvent;
//static void Say(string input)
//{
// Console.WriteLine("{0}", input);
//}
static void Main(string[] args)
{
Person jon = new Person(name: "Jon");
Person tom = new Person("Tom");
//SayEvent+=new StringProcessor(Say);
StringProcessor jonsVoice, tomsVoice, background;
jonsVoice = new StringProcessor(jon.Say);
tomsVoice = new StringProcessor(tom.Say);
background = new StringProcessor(Background.Note);
//jonsVoice += jon.Call;
//jonsVoice -= jon.Call;
//jonsVoice += delegate(string message) { Console.WriteLine("Anonymous"+message); };
jonsVoice += message => "Lambda :" + message;
//jonsVoice +=jon.Call ;
Console.WriteLine(jonsVoice(input: "Hello,son"));
Console.WriteLine(tomsVoice.Invoke("Hello,Daddy!"));
Console.WriteLine(background("An airplane flies past"));
Console.Read();
}
}
运行后结果如下:
泛型委托:Action<T>和Func<T,TResult>
Action<T>封装一个只有一个参数但是不具有返回值的方法。
如:
Action<string>PrintString=Console.WriteLine;
PrintString("It's a delegate");
Func<TResult>封装一个无返回值的方法。
Func<T,TResult>封装一个只有一个参数但是具有返回值的方法。
如:
Func<string> GetSingle = delegate() {return "It do not contain paramete"; };
Func<string, string> GetMessage = message => message;
PrintString(GetSingle());
PrintString(GetMessage("It's a delegate"));
多种委托方式的比较:
先看如下代码:
代码
int begintime = (DateTime.Now.Minute * 60 + DateTime.Now.Second) * 1000 + DateTime.Now.Millisecond;
for (int i = 0; i < 100000; i++)
{
StringProcessor jonsVoice = jon.Call;
jonsVoice("just a try");
}
int endtime = (DateTime.Now.Minute * 60 + DateTime.Now.Second) * 1000 + DateTime.Now.Millisecond;
int t = endtime - begintime;
for (int i = 0; i < 100000; i++)
{
StringProcessor jonsVoice = delegate(string message) { Console.WriteLine(message); };
jonsVoice("just a try");
}
begintime = (DateTime.Now.Minute * 60 + DateTime.Now.Second) * 1000 + DateTime.Now.Millisecond;
int tt = begintime - endtime;
for (int i = 0; i < 100000; i++)
{
StringProcessor jonsVoice = delegate(string message) { jon.Call(message); };
jonsVoice("just a try");
}
endtime = (DateTime.Now.Minute * 60 + DateTime.Now.Second) * 1000 + DateTime.Now.Millisecond;
int ttt = endtime - begintime;
for (int i = 0; i < 100000; i++)
{
StringProcessor jonsVoice = message => Console.WriteLine(message);
jonsVoice("just a try");
}
begintime = (DateTime.Now.Minute * 60 + DateTime.Now.Second) * 1000 + DateTime.Now.Millisecond;
int tttt = begintime - endtime;
Console.WriteLine("命名委托:{0},匿名委托:{1},匿名委托调用:{2},Lambda匿名方式:{3}", t, tt, ttt,tttt);
运行后的结果根据运行时的环境有很多种结果,但是 匿名委托效率最高 lambda委托效率次之可以肯定,而命名委托和匿名委托调用的效率却时有变化.