将谓词<T>转换为Func <T,bool>

Yel*_*low 18 c# linq

我有一个带有成员的类Predicate,我想在Linq表达式中使用它:

using System.Linq;

class MyClass
{

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

    private IEnumerable<Instrument> m_instrumentList;

    private Predicate<Instrument> m_filterExpression;
}
Run Code Online (Sandbox Code Playgroud)

当我读到" Predicate<T>[...]完全等同于Func<T, bool>"(见这里)时,我希望这可以起作用,因为All它作为参数:Func<Instrument, bool> predicate.

但是,我收到错误:

Argument 2: cannot convert from 'System.Predicate<MyNamespace.Instrument>' to 'System.Type'
Run Code Online (Sandbox Code Playgroud)

有没有办法将谓词转换为该函数将吞下的参数?

Jon*_*eet 16

这两种类型代表相同的逻辑签名,但这并不意味着它们只是可互换的.直分配将无法正常工作,例如-但你可以创建一个新的Func<T, bool>Predicate<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
Run Code Online (Sandbox Code Playgroud)

这有点像两个enum具有相同值的类型 - 您可以在它们之间进行转换,但您必须明确地进行转换.他们仍然是分开的类型.

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

public bool DoAllHaveSomeProperty()
{
    return m_instrumentList.All(new Func<T, bool>(m_filterExpression));
}
Run Code Online (Sandbox Code Playgroud)

当然,其他答案建议的lambda表达方法也会起作用.


Geo*_*vos 12

public bool DoAllHaveSomeProperty()
{
    return m_instrumentList.All(i => m_filterExpression(i));
}
Run Code Online (Sandbox Code Playgroud)

  • 它们在语义上是一样的.只是没有语法上的. (2认同)

Jul*_*lia 6

return m_instrumentList.All(i => m_filterExpression(i));
Run Code Online (Sandbox Code Playgroud)


Bri*_*ian 5

您可以通过调用Invoke将谓词转换为方法。所有代表都有这个成员。委托没有结构标识,但是方法可以转换为匹配的委托。此修补程序的性能成本较低,因为它增加了额外的间接层。但是,此问题的大多数解决方案都有该问题。埃里克·利珀特(Eric Lippert)在https://web.archive.org/web/20140625132124/http://blog.coverity.com/2014/06/18/delegates-structural-identity/中对此进行了详细讨论。

在您的特定情况下,请替换return m_instrumentList.All(m_filterExpression);return m_instrumentList.All(m_filterExpression.Invoke);

演示实际问题的示例代码。

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;
}
Run Code Online (Sandbox Code Playgroud)