当然,使用 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,微软希望这将缓解委托类型不兼容的问题。每个人的代表都可以很好地配合,因为他们只会根据他们的参数/返回类型进行匹配。
它并不能解决所有问题,因为Func(和Action)不能有out 或ref 参数,但那些不太常用。
更新:在 cmets Svish 中说:
仍然,从
函数到谓词和
回来,似乎没有做任何
区别?至少它仍然可以编译
没有任何问题。
是的,只要您的程序只将方法分配给委托,就像我的Main 函数的第一行一样。编译器默默地生成代码以新的委托对象转发到方法。所以在我的Main 函数中,我可以将x1 更改为ExceptionHandler2 类型而不会造成问题。
但是,在第二行,我尝试将第一个委托分配给另一个委托。即使认为第二个委托类型具有完全相同的参数和返回类型,编译器也会给出错误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
}
我的方法IsNegative 非常适合分配给p 和f 变量,只要我直接这样做。但是我不能将其中一个变量分配给另一个变量。