2014-08-27 17 views
9

bir doğrulama'yı dönüştürme: Ben Linq ifadede kullanmak istiyorum üyesi <code>Predicate</code> bir sınıf var, bir Func <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; 
} 

Ben Predicate<T> [...] tamamen "olduğunu okurken Func<T, bool> ile eşdeğer (see here), All bağımsız değişken olarak kabul edildiğinden, bunun işe yaramasını beklerim: Func<Instrument, bool> predicate.

Ancak, ben hata alıyorum:

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

bu işlev yutacak bir argüman için yüklemi dönüştürmek için bir yolu var mı?

cevap

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

Aha, bu işe yarar, teşekkürler! Dolayısıyla, ve Func nolu Predicate açık bir şekilde ** tamamen ** aynı değil, en azından semantik olarak değil! – Yellow

+1

Bunlar _are_ semantically aynı. Sadece sözdizimsel değil. –

+0

Oops, demek istediğim buydu. :-) – Yellow

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

iki tip aynı mantıksal imza temsil, ama bu onlar sadece interchangable olduğu anlamına gelmez. Düz bir ödev çalışmaz, örneğin - Predicate<T, bool>'dan yeni bir Func<T, bool> oluşturabilirsiniz. Örnek kod: - Eğer aralarında dönüştürebilirsiniz, ancak bunu açıkça yapmak zorunda

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

Bu biraz aynı değerlere sahip iki enum tip olması gibi. Onlar hala ayrı tipler. Senin durumunda

, bu yazabilirsiniz anlamı:

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

diğer cevaplar önerdiği lambda ifadesi yaklaşım elbette çok çalışacaktır.

1

Çok fazla cevap olduğundan, sadece eğlence için bir tane daha ekleyeceğim. İsterseniz sizin kod Sen Invoke çağırarak bir yönteme bir yüklemi dönüştürebilirsiniz aynı ad alanında

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

bu sınıfı ekle uzatma yöntemleri

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

    private IEnumerable<Instrument> m_instrumentList; 

    private Predicate<Instrument> m_filterExpression; 
} 

kullanabilirsiniz derlemek için. Tüm delegelerin bu üyesi var. Delegelerin yapısal kimliği yoktur, ancak yöntemler eşleşen delegelere dönüştürülebilir. Bu düzeltme, ekstra bir dolaylılık katmanı eklediğinden, küçük bir performans maliyetine sahiptir. Ancak, bu problemin çoğu çözümü bu soruna sahip. Eric Lippert bunu http://blog.coverity.com/2014/06/18/delegates-structural-identity numaralı telefondan daha ayrıntılı olarak anlatıyor. Belirli bir durumda

, return m_instrumentList.All(m_filterExpression.Invoke);

Örnek kod gerçek sorunu gösteren ile return m_instrumentList.All(m_filterExpression); değiştirin.

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; 
} 
İlgili konular