2014-08-27 54 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; 
} 
相關問題