2014-08-27 55 views
9

我有一个构件,其Predicate我想在一个LINQ表达式中使用的一类:转换一个谓语<T>到函数求<T, bool>

using System.Linq; 

class MyClass 
{ 

    public bool DoAllHaveSomeProperty() 
    { 
     return m_instrumentList.All(m_filterExpression); 
    } 

    private IEnumerable<Instrument> m_instrumentList; 

    private Predicate<Instrument> m_filterExpression; 
} 

正如我读“Predicate<T>是[...]完全相当于Func<T, bool>“(see here),我希望这个工作,因为All作为参数:Func<Instrument, bool> predicate

但是,我得到的错误:

Argument 2: cannot convert from 'System.Predicate<MyNamespace.Instrument>' to 'System.Type' 

有没有办法谓词转换成一个参数,这个函数会吞噬?

回答

7
public bool DoAllHaveSomeProperty() 
{ 
    return m_instrumentList.All(i => m_filterExpression(i)); 
} 
+0

啊哈,这工作,谢谢!所以Predicate 和Func 显然不是**完全相同,至少在语义上讲不是! – Yellow 2014-08-27 16:05:43

+1

它们在语义上是相同的。只是不在语法上。 – 2014-08-27 16:24:42

+0

糟糕,这就是我的意思。 :-) – Yellow 2014-08-28 08:02:30

6
return m_instrumentList.All(i => m_filterExpression(i)); 
9

这两种类型的代表相同的逻辑签名,但是,这并不意味着他们只是互换。例如,直接分配不起作用 - 但您可以从Predicate<T, bool>创建一个新的Func<T, bool>。示例代码:

Predicate<string> pred = x => x.Length > 10; 
// Func<string, bool> func = pred; // Error 
Func<string, bool> func = new Func<string, bool>(pred); // Okay 

这是一个有点像有两个enum类型具有相同的价值观 - 你可以在它们之间进行转换,但你必须这样做明确。他们仍然是不同的类型。

在你的情况,这意味着你可以写:

public bool DoAllHaveSomeProperty() 
{ 
    return m_instrumentList.All(new Func<T, bool>(m_filterExpression)); 
} 

通过其他的答案提出的lambda表达式的方法也可以工作,当然。

1

由于有很多答案,我将增加一个只是为了好玩。 如果你希望你的代码编译,你可以使用extention方法

//Original Code 
class MyClass4 
{ 
    public bool DoAllHaveSomeProperty() 
    { 
     return m_instrumentList.All(m_filterExpression); 
    } 

    private IEnumerable<Instrument> m_instrumentList; 

    private Predicate<Instrument> m_filterExpression; 
} 

添加这个类在同一个命名空间

public static class MyExtentions 
{ 
    public static bool All(this IEnumerable<Instrument> enumer, Predicate<Instrument> pred) 
    { 
     return enumer.All(e => pred(e)); 
    } 
} 
2

你可以通过调用调用谓词转换为方法。所有代表都有这个成员。代表没有结构标识,但可以将方法转换为匹配的代表。此修复程序的性能成本很低,因为它增加了一个额外的间接层。但是,这个问题的大多数解决方案都有这个问题。 Eric Lippert在http://blog.coverity.com/2014/06/18/delegates-structural-identity更详细地讨论了这一点。

在特定情况下,return m_instrumentList.All(m_filterExpression.Invoke);

示例代码演示实际问题更换return m_instrumentList.All(m_filterExpression);

void Main() 
{ 
    Predicate<int> t1 = Foo; 
    Func<int,bool> t2 = Foo; 
    Predicate<int> t3 = t2.Invoke; //Legal 
    Func<int,bool> t4 = t1.Invoke; //Legal 
    Predicate<int> t5 = t2; //Illegal 
    Func<int,bool> t6 = t1; //Illegal 
} 

bool Foo(int x) 
{ 
    return x > 20; 
} 
相关问题