当然使用Func
而不是特定委托的实际原因是C#将单独声明的委托视为完全不同的类型。
即使Func<int, bool>
并且Predicate<int>
都具有相同的参数和返回类型,它们也不是赋值兼容的。因此,如果每个库为每种委托模式声明了自己的委托类型,则除非用户插入“桥接”委托来执行转换,否则这些库将无法互操作。
// declare two delegate types, completely identical but different names:
public delegate void ExceptionHandler1(Exception x);
public delegate void ExceptionHandler2(Exception x);
// a method that is compatible with either of them:
public static void MyExceptionHandler(Exception x)
{
Console.WriteLine(x.Message);
}
static void Main(string[] args)
{
// can assign any method having the right pattern
ExceptionHandler1 x1 = MyExceptionHandler;
// and yet cannot assign a delegate with identical declaration!
ExceptionHandler2 x2 = x1; // error at compile time
}
通过鼓励所有人使用Func,Microsoft希望这将减轻不兼容的委托类型的问题。每个人的代表都可以一起玩,因为他们只是根据他们的参数/返回类型进行匹配。
它不能解决所有问题,因为Func
(和Action
)不能具有out
或ref
参数,但这些参数较少使用。
更新: Svish在评论中说:
不过,将参数类型从Func切换为Predicate并返回,似乎没有什么区别?至少它仍然可以毫无问题地进行编译。
是的,只要您的程序仅将方法分配给委托即可,就像我Main
函数的第一行一样。编译器以静默方式生成代码以创建新的委托对象,该委托对象继续转发到方法。因此,在我的Main
函数中,我可以更改x1
为type ExceptionHandler2
而不引起问题。
但是,在第二行中,我尝试将第一个委托分配给另一个委托。即使认为第二个委托类型具有完全相同的参数和返回类型,编译器也会给出error CS0029: Cannot implicitly convert type 'ExceptionHandler1' to '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; // Not allowed
}
只要直接为and 变量赋值,我的方法IsNegative
就是一件非常好的事情。但是,然后我无法将这些变量之一分配给另一个。p
f