为什么使用 Func<T,bool> 而不是 Predicate<T>?
题
这只是一个好奇的问题,我想知道是否有人有一个好的答案:
在 .NET Framework 类库中,我们有以下两个方法:
public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate
)
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
Func<TSource, bool> predicate
)
他们为什么使用 Func<TSource, bool>
代替 Predicate<TSource>
?似乎是 Predicate<TSource>
仅由以下人员使用 List<T>
和 Array<T>
, , 尽管 Func<TSource, bool>
几乎所有人都使用 Queryable
和 Enumerable
方法和扩展方法...那是怎么回事?
解决方案
尽管 Predicate
已同时推出 List<T>
和 Array<T>
, ,在.net 2.0中,不同的 Func
和 Action
变体来自.net 3.5。
所以那些 Func
谓词主要用于 LINQ 运算符中的一致性。从 .net 3.5 开始,关于使用 Func<T>
和 Action<T>
这 指导方针国家:
请使用新的 LINQ 类型
Func<>
和Expression<>
而不是自定义代表和谓词
其他提示
我以前不知道这一点。我喜欢Predicate<T>
委托 - 这是很好的和描述。然而,你需要考虑Where
的重载:
Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
这允许你基于条目,以及索引进行过滤。这是很好的和一致的,而
Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
不会
当然使用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
(和Action
)不能有out
或ref
参数,但这些不常用。
<强>更新强>评价Svish表示:
不过,从切换的参数类型 Func键谓语 回来了,似乎并没有作出任何 区别?至少它仍然编译 没有任何问题。
是的,只要你的程序只分配方法的代表们,在我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
变量,只要我这样做,直接一个非常好的事情。但是,我不能分配这些变量的其他中的一个。
(在3.5以上)的建议是使用Action<...>
和Func<...>
- “?为何”为 - 一个优势是,“Predicate<T>
”才有意义,如果你知道什么是“谓语”的意思 - 否则,你需要看的对象浏览器(等)找到signatute
相反Func<T,bool>
遵循标准图案;我可以立即告诉,这是一个函数,它接受一个T
并返回一个bool
- 并不需要了解所有术语 - 只需申请我的真心话测试
有关“断言”这可能是好的,但我很欣赏的企图规范。它还允许很多与该区域中的相关方法奇偶性。