1. 委托
From: http://www.cnblogs.com/daxnet/archive/2008/11/08/1687014.html
类是对象的抽象,而委托则可以看成是函数的抽象。一个委托代表了具有相同参数列表和返回值的所有函数。
class Program
{
delegate int CalculateDelegate(int a, int b);
int add(int a, int b)
{
return a + b;
}
static void Main(string[] args)
{
CalculateDelegate d = new Program().add;
//CalculateDelegate d = new CalculateDelegate(new Program().add);
Console.WriteLine(d(1, 2));
Console.ReadKey();
}
}
委托作为参数,在C#中非常常见。比如线程的创建,需要给一个ThreadStart或者ParameterizedThreadStart委托作为参数,而在线程执行的时候,将这个参数所指代的函数用作线程执行体。再比如:List<T>类型的Find方法的参数也是一个委托,它把“怎么去查找”或者说“怎么样才算找到”这个问题留给了开发人员。这有点像模板模式。
委托作为返回值一般会用在“根据不同情况决定使用不同的委托”这样的情形下。这有点像工厂模式。
2. 异步调用
From: http://www.cnblogs.com/daxnet/archive/2008/11/10/1687013.html
异步通过委托来完成。.net使用delegate来"自动"生成的异步调用是使用了另外的线程(而且是线程池线程)。
class Program
{
static TimeSpan Boil()
{
DateTime begin = DateTime.Now;
Console.WriteLine("水壶:开始烧水...");
Thread.Sleep(6000);
Console.WriteLine("水壶:水已经烧开了!");
return DateTime.Now - begin;
}
delegate TimeSpan BoilingDelegate();
static void Main(string[] args)
{
Console.WriteLine("小文:将水壶放在炉子上");
BoilingDelegate d = new BoilingDelegate(Boil);
IAsyncResult result = d.BeginInvoke(BoilingFinishedCallback, null);
Console.WriteLine("小文:开始整理家务...");
for (int i = 0; i < 20; i++)
{
Console.WriteLine("小文:整理第{0}项家务...", i + 1);
Thread.Sleep(1000);
}
}
static void BoilingFinishedCallback(IAsyncResult result)
{
AsyncResult asyncResult = (AsyncResult)result;
BoilingDelegate del = (BoilingDelegate)asyncResult.AsyncDelegate;
Console.WriteLine("(烧水一共用去{0}时间)", del.EndInvoke(result));
Console.WriteLine("小文:将热水灌到热水瓶");
Console.WriteLine("小文:继续整理家务");
}
}
EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke会使得调用线程阻塞,直到异步函数处理完成。EndInvoke调用的返回值也就是异步处理函数的返回值。
3. 泛型委托
[Serializable]
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs: EventArgs;
class IntEventArgs : System.EventArgs
{
public int IntValue { get; set; }
public IntEventArgs() { }
public IntEventArgs(int value)
{ this.IntValue = value; }
}
class StringEventArgs : System.EventArgs
{
public string StringValue { get; set; }
public StringEventArgs() { }
public StringEventArgs(string value)
{ this.StringValue = value; }
}
class Program
{
static void PrintInt(object sender, IntEventArgs e)
{
Console.WriteLine(e.IntValue);
}
static void PrintString(object sender, StringEventArgs e)
{
Console.WriteLine(e.StringValue);
}
static void Main(string[] args)
{
EventHandler<IntEventArgs> ihandler =
new EventHandler<IntEventArgs>(PrintInt);
EventHandler<StringEventArgs> shandler =
new EventHandler<StringEventArgs>(PrintString);
ihandler(null, new IntEventArgs(100));
shandler(null, new StringEventArgs("Hello World"));
}
}
4. 匿名方法
http://www.cnblogs.com/daxnet/archive/2008/11/12/1687011.html
只需要给出方法的参数列表(甚至也可以不给)以及方法具体实现,而不需要关心方法的返回值,更不必给方法起名字。最关键的是,只在需要的地方定义匿名方法,保证了代码的简洁。比如用于委托作为函数参数。
class Program
{
static void Main(string[] args)
{
List<string> names = new List<string>();
names.Add("Sunny Chen");
names.Add("Kitty Wang");
names.Add("Sunny Crystal");
List<string> found = names.FindAll(
delegate(string name)
{
return name.StartsWith("sunny",
StringComparison.OrdinalIgnoreCase);
});
if (found != null)
{
foreach (string str in found)
Console.WriteLine(str);
}
}
}
5. Lambda表达式
http://www.cnblogs.com/daxnet/archive/2008/11/14/1687010.html
从委托的角度来看,Lambda表达式与匿名方法没有区别。Lambda表达式的定义方式为:“([参数列表]) => 表达式”。
class Program
{
static void Main(string[] args)
{
List<string> names = new List<string>();
names.Add("Sunny Chen");
names.Add("Kitty Wang");
names.Add("Sunny Crystal");
List<string> found = names.FindAll
(
// Lambda Expression Implementation
name => name.StartsWith(
"sunny",
StringComparison.OrdinalIgnoreCase)
);
if (found != null)
{
foreach (string str in found)
Console.WriteLine(str);
}
}
}
6. 事件
http://www.cnblogs.com/daxnet/archive/2008/11/21/1687008.html
事件由委托定义。事件的触发方只需要确定好事件处理函数的签名即可。也就是说,触发方只需要定义在事件发生时需要传递的参数,而在订阅方,只需要根据这个签名定义一个处理函数,然后将该函数“绑定”到事件列表,就可以通过签名中的参数,对事件做相应的处理。