什么是C# 委托?这篇文章让你困惑全摆脱( 二 )


 csharp
d = method1;
同理,当进行 - 或者 -= 操作时,相当于把值赋给了委托变量 。
下面我们来看一下多播委托的例子:
 csharp
public delegate int DemoDelegate(int num);
static void Main(string[] args)
{
DemoDelegate dd = ;
dd += Square;
dd += Remainder;
dd(5);
Console.Read;
}
static int Square(int num)
{
Console.WriteLine(num * num);
return num * num;
}
static int Remainder(int num)
{
Console.WriteLine(num % 2);
return num % 2;
}
在代码中我们定义了两个方法,分别是计算数值平方的 Square 和计算数值除以2的余数Remainder。在 Main 方法中我们利用 += 将两个方法赋值给委托变量 dd  。执行这段代码,最终输出结果为:25、1 。当我们利用 - 或者 -= 来移除掉一个方法时,例如移除掉 Square,这时就只会输出1,当我们把所有的方法都移除掉时,程序运行起来将会报空指针异常的错误 。
注意:
1. 委托不可变,使用 **+=** 或者 **-=** 实际上是创建了新的委托实例,并把它付给当前的委托变量 。
2. 如果多播委托的返回类型不是void,那么调用者只能获取到最后一个被调用方法的返回值,前面方法的返回值将会被抛弃 。
3. c#会将 +、-、+=、-=编译为 Combine 和 Remove两个方法 。
 3.实例方法委托和静态方法委托 
实例方法和静态方法都是c#中经常用到的方法,我们可以将这两种方法都赋值给委托,因此就出现了实例方法稳妥和静态方法委托 。它们之间的区别如下:1. 一个实例方法被赋值给委托对象时,委托对象不仅要保留对方法的引用,还要保留方法所属实例的引用,这时 System.Delegate 中的Target 属性就表示的是方法所属的实例;
2. 一个静态方法赋值给委托对象时,Target 属性值为 。例子如下:- 首先定义一个类 Demo 里边包含 NumAdd 实例方法和 Num 静态方法
 csharp
class Demo
{
public int NumAdd(int num)
{
return ++num;
}
public static int Num(int num)
{
return num;
}
}
接着在控制台中调用这两个方法
 csharp
public delegate int DemoDelegate(int num);
class Program
{
static void Main(string[] args)
{
Demo demo = new Demo;
DemoDelegate dd = demo.NumAdd;
dd(2);
Console.WriteLine("方法所属实例:"+dd.Target);
Console.WriteLine("调用方法:"+dd.Method);
DemoDelegate staticDd = Demo.Num;
staticDd(2);
Console.WriteLine("方法所属实例:" + staticDd.Target);
Console.WriteLine("调用方法:" + staticDd.Method);
Console.ReadLine;
}
}
运行以上代码,输出结果如下:

什么是C# 委托?这篇文章让你困惑全摆脱

文章插图
我们可以看到,将静态方法赋值给委托对象后打印方法所属实例为空 。
 4.泛型委托类型 
在一些情况下我们不确定参数类型和返回值类型,这时我们就需要用到泛型委托类型,语法如下:
 csharp
public delegate T DemoDelegate<T>(T arg);
我们具体看一下例子:
 csharp
public delegate T DemoDelegate<T>(T num);
class Demo
{
public int NumAdd(int num)
{
return ++num;
}
}
class Program
{
static void Main(string[] args)
{
Demo demo = new Demo;
DemoDelegate<int> dd = demo.NumAdd;
Console.WriteLine(dd(2));
Console.ReadLine;
}
}
运行上面的代码,控制台将会输出结果 3
注意:我们可以将返回值类型或者参数类型固定,例如:
 csharp
public delegate string DemoDelegate<T>(T arg);
public delegate T DemoDelegate<T>(int arg);
使用泛型委托的好处是可以写出一组委托类型,这组方法可以拥有热议类型的返回值和任意数量的参数 。下一小节我们就来看一下具体怎么用 。
 
5.Action 和 Func 
1. Func
Func是一个具有返回类型的方法,它的类型参数数量可以多达16个,其中包括0到多个输入类型参数和一个输出类型参数 。下面的代码段展示了Func部分类型参数:
 csharp
delegate void Action;
delegate void Action<in T> (T t);
delegate void Action(in T1,in T2)(T t1,T t2);
2. Action


推荐阅读