【问题标题】:FindAll - Predicate<TSource> vs Func<TSource, bool>FindAll - Predicate<TSource> vs Func<TSource, bool>
【发布时间】:2018-03-11 21:36:05
【问题描述】:

我很难理解为什么List&lt;T&gt;FindAll(...) 方法不接受Func&lt;TSource, bool&gt;,而是坚持接受Predicate&lt;TSource&gt;

因此,当我有 List 的书籍时,我只想购买比 10 便宜的书籍。这段代码运行得很好。

  Predicate<Book> CheapBooksPredicate = b => b.Price < 10;
  var cheapBooksPredicate = books.FindAll(CheapBooksPredicate);

但是当我将Predicate&lt;TSource&gt; 更改为Func&lt;TSource, bool&gt;

   Func<Book, bool> CheapBooksFunc = b => b.Price < 10;
   var cheapBooksFunc = books.FindAll(CheapBooksFunc);

我收到错误:

参数 1:无法从 'System.Func' 转换为 'System.Predicate'

我在这里缺少什么?当Func&lt;TSource, bool&gt;Predicate&lt;TSource&gt; 都是predicates 时。 Predicate&lt;TSource&gt; 应该是 Func 的专用版本,它根据一组标准获取并评估一个值并返回一个布尔值,因此我认为它们可以在使用方面相互替换。

【问题讨论】:

  • FindAll 的定义早于Func&lt;&gt; 委托家族的定义,因此他们为自己的特定情况创建了自己的委托类型。委托类型与 .NET 中的所有其他类型一样,由于结构相似性,因此不兼容赋值。类型的名称很重要。
  • 只需使用 LINQ:.Where(...)
  • @mikez 所以即使两者都做同样的事情,但他们有不同的名字,编译器会把它们当作两种不同的类型?
  • @Nashmár 是的。您可能会从 this question 获得更多见解,尤其是 Eric Lippert 的 cmets 和他的回答 here。简而言之,如果编译器/运行时团队不得不重新做一遍,他们可能会选择为委托实现结构类型,但到目前为止,这将是一个重大变化,这意味着它不太可能发生。
  • @mikez 我想我现在明白了。谢谢。

标签: c# .net


【解决方案1】:

它们具有相同的签名,但它们是根本不同的类型,不能转换为保留引用的转换。由于FindAll 想要Predicate&lt;T&gt;:使用Predicate&lt;T&gt;

如果它们可以像这样可铸造会很好吗?也许吧,但这需要 CLR 和语言更改,而且不太可能发生。

【讨论】:

    【解决方案2】:

    您可以使用以下扩展方法将Func&lt;T, bool&gt;转换为Predicate&lt;T&gt;

    static Predicate<T> FuncToPredicate<T>(Func<T, bool> func)
    {
       return new Predicate<T>(func);
    }
    

    Reference

    【讨论】:

      猜你喜欢
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 2022-11-28
      • 1970-01-01
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多