Delegate实际上是一个类型(class)。这一点我们可以做一个实验例子。
using System;
delegate void Print(string message);
sealed class Testing
{
public static void Execute(Print p)
{
p("testing");
}
}
sealed class Program
{
static void prt(string str){ Console.WriteLine(str); }
static void Main(string[] args)
{
Testing.Execute(prt);
}
}
然后我们通过IL代码观察:

代理,也就是delegate Print 实际上是一个sealed class ,见 特征1 ,继承于System.MulticastDelegate
特征2 更明显,直接说明了Print就是一个class
构造函数和两个多线程方法我们暂且不谈, 这里的重点是它具备一个Invoke 方法, 类型是void, 签名类型是string 。
我们用两个方法来试探一下这个Invoke是什么, 首先,我们通过代码调用顺序,查找一下Testing 类的静态方法 Execute(Print p) 做了些什么:

实际上调用了Print对象的Invoke 方法,参数就是之前压入栈的“string”。 这下我们明白了, Invoke方法就是我们定义的 delegate void Print(string message); 的真身。
再来一个方法证实一下这个猜测,我们修改一下C#源代码:
using System;
delegate void Print(string message);
delegate void Dele2(int i, DateTime d); //增加一个新的代理
sealed class Testing
{
public static void Execute(Print p , Dele2 d)
{
p("testing");
d(10, DateTime.Now);
}
}
sealed class Program
{
static void prt(string str){ Console.WriteLine(str); }
static void ptr2(int i, DateTime d)
{
Console.WriteLine(string.Format("{0},{1}",i,d));
}
static void Main(string[] args)
{
Testing.Execute(prt,ptr2);
}
}
然后我们再来看看生成IL代码:

这下勿须置疑了,我们可以这样子认为:
Delegate 实际上就是一个特殊的类型,只不过是我们的声明的时候可以简化写法,系统实际上还是会编译为sealed class , 在这个特殊的类中,会使用一个拥有相同签名的方法来实际执行。
最后,做一次验证,我们再修改一下代码:
using System;
delegate void Print(string message);
delegate void Dele2(int i, DateTime d);
sealed class Testing
{
public static void Execute(Print p , Dele2 d)
{
p.Invoke("testing"); //改动点
d.Invoke(10, DateTime.Now); //改动点
//我们直接调用它们的Invoke方法
}
}
sealed class Program
{
static void prt(string str){ Console.WriteLine(str); }
static void ptr2(int i, DateTime d)
{
Console.WriteLine(string.Format("{0},{1}",i,d));
}
static void Main(string[] args)
{
Testing.Execute(prt,ptr2);
}
}
成功执行:
