当前位置:  开发笔记 > 编程语言 > 正文

为什么Func <T,bool>而不是Predicate <T>?

如何解决《为什么Func<T,bool>而不是Predicate<T>?》经验,为你挑选了4个好方法。

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

在.NET Framework类库中,我们有两个方法:

public static IQueryable Where(
    this IQueryable source,
    Expression> predicate
)

public static IEnumerable Where(
    this IEnumerable source,
    Func predicate
)

他们为什么用Func而不是Predicate?好像Predicate只由ListArray,而Func所使用的几乎所有QueryableEnumerable方法和扩展方法...什么与怎么了?



1> Jb Evain..:

虽然Predicate已经同时推出了,List并且Array在.net 2.0中,不同的FuncAction变体来自.net 3.5.

因此,这些Func谓词主要用于LINQ运算符的一致性.作为.NET 3.5,有关使用的FuncAction的方针状态:

使用新的LINQ类型Func<>Expression<>不是自定义委托和谓词


很酷,从未见过那些guildelines =)
将接受这个作为答案,因为它有最多的选票.因为Jon Skeet有很多代表...:p
这是一个奇怪的指导方针.当然它应该声明"使用新的LINQ类型"Func <>"和"Action <>"[...]".表达式<>是完全不同的东西.
好吧,实际上你必须将它放在指南的上下文中,这是关于编写LINQ提供程序.所以,对于LINQ运算符,指南是使用Func <>和Expression <>作为扩展方法的参数.我同意我对使用Func和Action的单独指南表示赞赏

2> Jon Skeet..:

我以前想过这个.我喜欢这个Predicate代表 - 这很好,很有描述性.但是,您需要考虑以下的重载Where:

Where(IEnumerable, Func)
Where(IEnumerable, Func)

这允许您根据条目的索引进行过滤.那是好的和一致的,而:

Where(IEnumerable, Predicate)
Where(IEnumerable, Func)

不会.


谓词会有点难看 - 谓词通常(计算机科学的IME)基于单个值.它当然可以是Predicate >,但这甚至更丑:)
嗯,刚才看到我错误地写了第一条评论:P我的建议当然是Predicate ...
可以有Predicate ?但我明白你的观点=)
由于指导原则,接受了另一个答案.希望我能说出不止一个答案!如果我能将一些答案标记为"非常值得注意"或"除了答案之外还有一个应该注意的好点",那将会很好
@JonSkeet我知道这个问题已经很老了,但是知道什么具有讽刺意味吗?“在哪里”扩展方法中的参数名称为“谓词”。嘿= P。

3> Daniel Earwi..:

当然,使用Func而不是特定委托的实际原因是C#将单独声明的委托视为完全不同的类型.

即使FuncPredicate两者具有相同的参数和返回类型,它们不是赋值兼容.因此,如果每个库都为每个委托模式声明了自己的委托类型,那么除非用户插入"桥接"委托来执行转换,否则这些库将无法互操作.

    // 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,Microsoft希望这将缓解不兼容的委托类型的问题.每个人的代表都会很好地一起玩,因为他们只会根据他们的参数/返回类型进行匹配.

它没有解决所有问题,因为Func(和Action)不能有outref参数,但那些不太常用.

更新: 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 p = IsNegative;
    Func f = IsNegative;

    p = f; // Not allowed
}

我的方法IsNegative是分配到一个非常好的东西pf变数,只要我这样做直接.但后来我无法将其中一个变量分配给另一个变量.



4> Marc Gravell..:

建议(3.5及以上)是使用Action<...>Func<...>- 为"为什么?" - 一个优点是" Predicate"只有在你知道"谓词"意味着什么时才有意义 - 否则你需要查看对象浏览器(等)以找到signatute.

反过来Func遵循标准模式; 我可以立即告诉我这是一个功能,需要一个T并返回一个bool- 不需要理解任何术语 - 只需应用我的真实测试.

对于"谓词",这可能没问题,但我很欣赏标准化的尝试.它还允许与该区域中的相关方法进行大量奇偶校验.

推荐阅读
小色米虫_524
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有