1.5 内置委托
  上述几种委托的使用,都没能离开定义委托类型这一步骤。微软干脆直接把定义委托这一步骤封装好,形成三个泛型类:Action、Func和Predicate,这样省去了定义的步骤,推荐使用。
  C#
public class Program
{
public static void Main(string[] args)
{
//Action
Actionstring> action = delegate(string str) { Console.WriteLine("你好!" + str); };
action("GG");
//Func
Funcint, int, int> func = delegate(int x, int y) { return x + y; };
Console.WriteLine("计算结果:" + func(5, 6));
//Predicate
Predicatebool> per = delegate(bool isTrue) { return isTrue == true; };
Console.WriteLine(per(true));
}
}
  它们的区别如下:
  Action委托:允许封装的方法有多个参数,不能有返回值;
  Func委托:允许封装的方法有多个参数,必须有返回值;
  Predicate委托:允许封装的方法有一个参数,返回值必须为bool类型。
  2. 事件
  委托是一种类型,事件依赖于委托,故事件可以理解为是委托的一种特殊实例。它和普通的委托实例有什么区别呢?委托可以在任意位置定义和调用,但是事件只能定义在类的内部,只允许在当前类中调用。所以说,事件是一种类型安全的委托。
  2.1 定义事件
  通过一个简单的场景来演示下事件的使用:
  C#
///
/// 音乐播放器
///
public class MusicPlayer
{
//step01:定义 音乐播放结束 事件
public event EventHandler PlayOverEvent;
public string Name { get; set; }
public MusicPlayer(string name)
{
this.Name = name;
}
//step02:定义一个触发事件的方法
public void PlaySong()
{
//模拟播放
Console.WriteLine("正在播放歌曲:" + this.Name);
for (int i = 0; i 20; i++)
{
Console.Write(".");
Thread.Sleep(100);
}
//播放结束,则触发PlayOverEvent事件
if (PlayOverEvent != null)
{
PlayOverEvent(this, null);
}
}
}
public class Program
{
static void Main(string[] args)
{
//创建音乐播放器对象
MusicPlayer player = new MusicPlayer("自由飞翔");
//step03:注册事件
player.PlayOverEvent += player_PlayOverEvent;
//播放歌曲,结束后触发事件
player.PlaySong();
Console.ReadKey();
}
static void player_PlayOverEvent(object sender,EventArgs e)
{
MusicPlayer player = sender as MusicPlayer;
Console.WriteLine("rn{0}播完了!", player.Name);
}
}
  程序运行结果:
  (1)总结上面事件使用的几个步骤:
  step01:用event关键字定义事件,事件必须要依赖一个委托类型;
  step02:在类内部定义触发事件的方法;
  step03:在类外部注册事件并引发事件。
  (2)public event EventHandler PlayOverEvent
  这句代码在MusicPlayer类定义了一个事件成员PlayOverEvent,我们说事件依赖于委托、是委托的特殊实例,所以EventHandler肯定是一个委托类型。下面我们来验证一下:
  EventHandler是微软封装好的事件委托,该委托没有返回值类型,两个参数:sender事件源一般指的是事件所在类的实例;TEventArgs事件参数,如果有需要创建,要显示继承System.EventArgs。
  2.2 事件的本质
  C#
  MusicPlayer player = new MusicPlayer("自由飞翔");
  //注册事件
  player.PlayOverEvent += player_PlayOverEvent;
  player.PlaySong();
  从上面代码我们观察到,事件要通过”+=”符号来注册。我们猜想,事件是不是像多播委托一样通过Delegate.Combine方法可以绑定多个方法?还是通过反编译工具查看下:
  我们看到PlayOverEvent事件内部生成了两个方法:add_ PlayOverEvent和remove_ PlayOverEvent。add方法内部调用Delegate.Combine把事件处理方法绑定到委托列表;remove方法内部调用Delegate.Remove从委托列表上移除指定方法。其实,事件本质上是一个多播委托。