将Predicate转换为Func
将Predicate转换为Func
我有一个类,其中有一个成员Predicate
,我想在Linq表达式中使用它:
using System.Linq; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerablem_instrumentList; private Predicate m_filterExpression; }
正如我在这里所读到的"Predicate
是[...]与Func
完全等效的",所以我期望这个可以工作,因为All
接受的参数是:Func
。
然而,我得到了错误:
Argument 2: cannot convert from 'System.Predicate' to 'System.Type'
有没有办法将这个谓词转换为该函数可以接受的参数?
将Predicate
解决方法是通过将m_filterExpression委托转换为Func
return m_instrumentList.All(i => m_filterExpression(i));
这样做的原因是Predicate
需要注意的是,这种转换可能会带来一些额外的开销。作者在代码中提到了这一点,并表示已经对其进行了测量,发现它不会被编译或JIT优化掉。因此,使用此转换可能会对性能产生一些影响,需要注意。
问题的出现原因是Predicate
在代码中,可以使用以下方式进行转换:
Predicatepred = x => x.Length > 10; // Func func = pred; // 错误 Func func = new Func (pred); // 正确
这有点像有两个具有相同值的枚举类型 - 你可以在它们之间进行转换,但是必须明确地进行转换。它们仍然是不同的类型。
在你的情况下,这意味着你可以这样编写:
public bool DoAllHaveSomeProperty() { return m_instrumentList.All(new Func(m_filterExpression)); }
当然,其他答案中提到的lambda表达式方法也可以正常工作。
使用new Func
将Predicate
在具体的案例中,可以通过调用Invoke来将谓词转换为方法。所有委托都有这个成员。以下是具体的代码示例:
void Main() { Predicatet1 = Foo; Func t2 = Foo; Predicate t3 = t2.Invoke; //合法 Func t4 = t1.Invoke; //合法 Predicate t5 = t2; //不合法 Func t6 = t1; //不合法 } bool Foo(int x) { return x > 20; }
在解决这个问题时,只需要将`return m_instrumentList.All(m_filterExpression);`替换为`return m_instrumentList.All(m_filterExpression.Invoke);`即可。这样就将谓词转换为了方法。