这只是一个好奇的问题,我想知道是否有人有一个好的答案:

在 .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> 几乎所有人都使用 QueryableEnumerable 方法和扩展方法...那是怎么回事?

有帮助吗?

解决方案

尽管 Predicate 已同时推出 List<T>Array<T>, ,在.net 2.0中,不同的 FuncAction 变体来自.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)不能有outref参数,但这些不常用。

<强>更新评价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是分配给pf变量,只要我这样做,直接一个非常好的事情。但是,我不能分配这些变量的其他中的一个。

(在3.5以上)的建议是使用Action<...>Func<...> - “?为何”为 - 一个优势是,“Predicate<T>”才有意义,如果你知道什么是“谓语”的意思 - 否则,你需要看的对象浏览器(等)找到signatute

相反Func<T,bool>遵循标准图案;我可以立即告诉,这是一个函数,它接受一个T并返回一个bool - 并不需要了解所有术语 - 只需申请我的真心话测试

有关“断言”这可能是好的,但我很欣赏的企图规范。它还允许很多与该区域中的相关方法奇偶性。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top