2013-03-06 22 views
2

給下面的一段代碼:委託組合不端行爲

List<string> aux = new List<string>(); 

aux.Add("a"); 
aux.Add("ab"); 
aux.Add("ac"); 
aux.Add("abc"); 
aux.Add("b"); 
aux.Add("bc"); 
aux.Add("c"); 
aux.Add("e"); 
aux.Add("f"); 

Func<string, bool> searchForA = (f => f.Contains("a")); 
Func<string, bool> searchForC = (f => f.Contains("c")); 
Func<string, bool> searchForF = (f => f.Contains("f")); 

可有人請給我爲什麼這個電話

aux.Where(searchForA + searchForF + searchForC).ToList(); 

返回 「交流」, 「ABC」, 「BC」,並解釋「 C」這是同樣的結果

aux.Where(searchForC).ToList(); 

我的意思是,哪來‘第一查詢’和‘AB’和‘F’?

編輯:我用委託組合,因爲我想動態定義搜索模式!

EDIT2:對於新片的示例代碼主要編輯檢查,這個問題IM tryng解決

string[] searchFor = "a c f".Split(' '); 

Func<string, bool>[] delegates = new Func<string, bool>[searchFor.Length]; 
for (int i = 0; i < searchFor.Length; i++) 
{ 
    string search = searchFor[i]; // Make sure the lambda does not capture a loop variable! 
    delegates[i] = new Func<string, bool>(f => f.Contains(search)); 
} 

List<string> aux = new List<string>(); 
aux.Add("a"); 
aux.Add("ab"); 
aux.Add("ac"); 
aux.Add("abc"); 
aux.Add("b"); 
aux.Add("bc"); 
aux.Add("c"); 
aux.Add("e"); 
aux.Add("f"); 

List<string> result = aux.Where((Func<string, bool>)Delegate.Combine(delegates)).ToList(); 
+0

我不知道是什麼'+'確實爲代表,但你應該使用'||'或''&&。 – 2013-03-06 21:00:28

+0

@HighCore邏輯運算符「AND」和「OR」對代表無效 – Leonardo 2013-03-06 21:05:23

+1

@Leonardo你是對的。那麼它應該是'.Where(x => SearchForA(x)|| searchForC(x))' – 2013-03-06 21:06:56

回答

13

調用兩個非空返回代表的組合具有語義「調用第一個,丟棄結果,呼叫第二個,返回結果「。它沒有語義「如果它們碰巧返回bool」,則將它們兩者都調用並且結果爲or。請記住,委託組合必須適用於任何委託類型;爲什麼運行時選擇or語義爲bool返回代表而不是and語義?對於返回string的代表,它應該做什麼?連接字符串?如果你結合int返回的代表是否應該添加數字?

合併結果的問題不能以一致的方式解決,所以選擇是忽略除最後一個以外的所有結果。

如果你想or兩個謂詞在一起,那麼你可以很容易地自己做。這裏有一個方便的擴展方法:

static Func<T, bool> Or<T>(this Func<T, bool> f1, Func<T, bool> f2) 
{ return t => f1(t) || f2(t); } 

,現在你可以說

...Where(searchForA.Or(searchForC).Or(searchForF))... 

您還可以延伸到多個代表:

static Func<T, bool> OrMany<T>(params Func<T, bool>[] fs) 
{ 
    Func<T, bool> result = t => false; 
    foreach(Func<T, bool> f in fs) 
     result = result.Or(f); 
    return result; 
} 

現在你可以使用「擴展形式」與代表名單:

...Where(OrMany(searchForA, searchForC, searchForf))... 

或「未展開的形式」與代表的數組:

Func<string, bool>[] delegates = whatever; 
...Where(OrMany(delegates))... 
+0

謝謝!你幾乎可以理解我的原始問題......事情是,我想使用超過2個代表進行搜索...我進一步編輯了這個問題 – Leonardo 2013-03-06 21:11:18

+1

@Leonardo:你可以使用我給你合併的任意數量的「與會代表。 – 2013-03-06 21:14:25

+0

我做了進一步的編輯,但它似乎與OrMany計算出來...虐待它測試 – Leonardo 2013-03-06 21:19:06