Svi*_*ish 207 .net c# predicate func
这只是一个好奇的问题,我想知道是否有人有一个很好的答案:
在.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
)
Run Code Online (Sandbox Code Playgroud)
他们为什么用Func<TSource, bool>而不是Predicate<TSource>?好像Predicate<TSource>只由List<T>和Array<T>,而Func<TSource, bool>所使用的几乎所有Queryable和Enumerable方法和扩展方法...什么与怎么了?
Jb *_*ain 162
虽然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<>不是自定义委托和谓词
Jon*_*eet 111
我以前想过这个.我喜欢这个Predicate<T>代表 - 这很好,很有描述性.但是,您需要考虑以下的重载Where:
Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
Run Code Online (Sandbox Code Playgroud)
这允许您根据条目的索引进行过滤.那是好的和一致的,而:
Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
Run Code Online (Sandbox Code Playgroud)
不会.
Dan*_*ker 30
当然,使用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
}
Run Code Online (Sandbox Code Playgroud)
通过鼓励每个人使用Func,Microsoft希望这将缓解不兼容的委托类型的问题.每个人的代表都会很好地一起玩,因为他们只会根据他们的参数/返回类型进行匹配.
它没有解决所有问题,因为Func(和Action)不能有out或ref参数,但那些不太常用.
更新: Svish在评论中说:
仍然,将参数类型从Func切换到Predicate并返回,似乎没有任何区别?至少它仍然没有任何问题编译.
是的,只要你的程序只为代理分配方法,就像我的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
}
Run Code Online (Sandbox Code Playgroud)
我的方法IsNegative是分配到一个非常好的东西p和f变数,只要我这样做直接.但后来我无法将其中一个变量分配给另一个变量.
Mar*_*ell 28
建议(3.5及以上)是使用Action<...>和Func<...>- 为"为什么?" - 一个优点是" Predicate<T>"只有在你知道"谓词"意味着什么时才有意义 - 否则你需要查看对象浏览器(等)以找到signatute.
反过来Func<T,bool>遵循标准模式; 我可以立即告诉我这是一个功能,需要一个T并返回一个bool- 不需要理解任何术语 - 只需应用我的真实测试.
对于"谓词",这可能没问题,但我很欣赏标准化的尝试.它还允许与该区域中的相关方法进行大量奇偶校验.
| 归档时间: |
|
| 查看次数: |
52986 次 |
| 最近记录: |