使用Func
而不是特定委托的实际原因是C#将分别声明的委托视为完全不同的类型。
尽管Func<int, bool>
和Predicate<int>
都具有相同的参数和返回类型,但它们不能进行赋值兼容。 因此,如果每个库都为每个委托模式声明自己的委托类型,那么这些库将无法互操作,除非用户插入“桥接”委托来执行转换。
public delegate void ExceptionHandler1(Exception x);
public delegate void ExceptionHandler2(Exception x);
public static void MyExceptionHandler(Exception x)
{
Console.WriteLine(x.Message);
}
static void Main(string[] args)
{
ExceptionHandler1 x1 = MyExceptionHandler;
ExceptionHandler2 x2 = x1;
}
通过鼓励所有人使用Func,微软希望能够缓解不兼容委托类型的问题。每个人的委托将友好地相互配合,因为它们将基于它们的参数/返回类型进行匹配。
这并不能解决所有问题,因为Func(和Action)不能具有out或ref参数,但这些用得较少。
更新:在评论中Svish说:
“仍然,将参数类型从Func更改为Predicate,再改回来,似乎没有任何区别?至少它仍然可以编译而没有任何问题。”
是的,只要您的程序只分配方法给委托,就像我的Main函数的第一行一样。编译器会默默地生成代码以新建一个委托对象,并将其转发到该方法。因此,在我的Main函数中,我可以将x1更改为ExceptionHandler2类型而不会引起问题。
然而,在第二行中,我尝试将第一个委托分配给另一个委托。即使第二个委托类型具有完全相同的参数和返回类型,编译器也会给出错误信息CS0029:“无法隐式将类型'ExceptionHandler1'转换为'ExceptionHandler2'”。
也许这会让它更清楚:
public static bool IsNegative(int x)
{
return x < 0;
}
static void Main(string[] args)
{
Predicate<int> p = IsNegative;
Func<int, bool> f = IsNegative;
p = f;
}
只要我直接将方法 IsNegative
分配给变量 p
和 f
,那么这是完全可以的。但是,如果我将其中一个变量分配给另一个变量,则会出现问题。
delegate bool Tester(int i)
的示例。System.Predicate<T>
不是自定义的。 - GSergPredicate<T>
的论据(除非您认为Predicate<T>
是自定义委托)。 - bornfromanegg