Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么是Func<;T、 布尔>;而不是谓词<;T>;?_C#_.net_Predicate_Func - Fatal编程技术网

C# 为什么是Func<;T、 布尔>;而不是谓词<;T>;?

C# 为什么是Func<;T、 布尔>;而不是谓词<;T>;?,c#,.net,predicate,func,C#,.net,Predicate,Func,这只是一个好奇的问题,我想知道是否有人有一个好的答案: 例如,在.NET Framework类库中,我们有以下两种方法: public static IQueryable<TSource> Where<TSource>( this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate ) public static IEnumerab

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

例如,在.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
)
公共静态IQueryable,其中(
这是可靠的消息来源,
表达式谓词
)
公共静态IEnumerable在哪里(
这是一个数不清的来源,
Func谓词
)

为什么他们使用
Func
而不是
谓词
?似乎
谓词
仅由
列表
数组
使用,而
函数
几乎被所有
可查询
可枚举
方法和扩展方法使用。。。这是怎么回事?

虽然
谓词
是在
列表
数组
的同时引入的,但在.net 2.0中,不同的
函数
动作
变体来自.net 3.5

因此,这些
Func
谓词主要用于LINQ运算符中的一致性。从.net 3.5开始,关于使用
Func
Action

务必使用新的LINQ类型
Func
表达式
而不是自定义 委托和谓词


我以前就想知道这一点。我喜欢
谓词
委托-它很好而且具有描述性。但是,您需要考虑<代码>的重载,其中< /C> >:

Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
其中(IEnumerable,Func)
其中(IEnumerable,Func)
这也允许您根据条目的索引进行筛选。这很好,而且前后一致,然而:

Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)
Where(IEnumerable,谓词)
其中(IEnumerable,Func)
不可能。

建议(在3.5和更高版本中)使用
操作和
函数来解释“为什么?”-一个优点是“
谓词
”只有在您知道“谓词”的含义时才有意义-否则您需要查看对象浏览器(etc)来查找符号

相反地,
Func
遵循标准模式;我可以立即看出,这是一个函数,它接受一个
T
,并返回一个
bool
——不需要理解任何术语——只要应用我的真值测试即可


对于“谓词”,这可能还可以,但我很欣赏标准化的尝试。它还允许与该领域中的相关方法进行大量对等。

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

尽管
Func
Predicate
都有相同的参数和返回类型,但它们与赋值不兼容。因此,如果每个库都为每个委托模式声明了自己的委托类型,那么除非用户插入“桥接”委托来执行转换,否则这些库将无法进行互操作

    // 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,微软希望这将缓解委托类型不兼容的问题。每个人的代理都会很好地配合,因为它们只会根据其参数/返回类型进行匹配

它不能解决所有问题,因为
Func
(和
Action
)不能有
out
ref
参数,但这些参数不太常用

更新:斯维什在评论中说:


不过,从 Func to谓词和 回来,似乎没什么意义 区别?至少它还能编译 没有任何问题

是的,只要您的程序只为代理分配方法,就像我的
Main
函数的第一行一样。编译器以静默方式生成代码,将新的委托对象转发给该方法。因此,在我的
Main
函数中,我可以将
x1
更改为
ExceptionHandler2
类型,而不会引起问题

但是,在第二行,我尝试将第一个委托分配给另一个委托。即使第二个委托类型具有完全相同的参数和返回类型,编译器也会给出错误
CS0029:无法将类型“ExceptionHandler1”隐式转换为“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
}
公共静态bool为负(int x)
{
返回x<0;
}
静态void Main(字符串[]参数)
{
谓语p=IsNegative;
Func f=负;
p=f;//不允许
}

我的方法
IsNegative
非常适合分配
p
f
变量,只要我直接这样做。但是我不能将这些变量中的一个分配给另一个。

酷,以前从未见过这些Guillideline=)会接受这个答案,因为它拥有最多的选票。因为Jon Skeet有很多代表性这是一个奇怪的指导方针。当然,它应该声明“确实使用新的LINQ类型”Func“和”Action“[…]”。表达式是一个完全不同的东西。实际上,您必须将它放在指南的上下文中,这是关于编写LINQ提供程序的。是的,对于LINQ操作符,准则是使用Func和Expression作为扩展方法的参数。我同意,我希望有一个单独的关于使用Func和action的指南。我认为Skeet的观点是,表达式不是指南。这是C#编译器的一项功能,用于识别该类型并对其执行不同的操作。谓词会有点难看——谓词通常(计算机科学的IME)基于单个值进行谓词。当然可以是谓词,但那更难看:)真的。。。呵呵。不,我想Func比较干净。因为指南,我接受了另一个答案。但愿我能记下不止一个答案!如果我能将一些答案标记为“非常值得注意”或“除了答案之外还有一个值得注意的要点”,那就太好了。嗯,我刚刚看到我把第一条评论写错了:P我的建议当然是谓词…@JonSkeet I