2016-12-29 22 views
2

我寫了下面的代碼,我無法理解它爲什麼只返回兩個元素而不是全部。它看起來像「Where」方法只適用於最後添加的方法。使用多種方法的LINQ表達式

class Person 
{ 
    public int Age { get; set; } 
    public string Name { get; set; } 
} 

class Program 
{ 
    public static bool IsAdult(Person person) 
    { 
     return person.Age > 18; 
    } 

    public static bool MethodTrue(Person person) 
    { 
     return true; 
    } 

    static void Main() 
    { 
     var list = new List<Person> 
     { 
      new Person() { Age = 20, Name = "Artur" }, 
      new Person() { Age = 30, Name = "Adam" }, 
      new Person() { Age = 10, Name = "Wieslaw" }, 
      new Person() { Age = 15, Name = "Michal" } 
     }; 


     Func<Person, bool> predicate = null; 
     predicate += MethodTrue; 
     predicate += IsAdult; 

     var res = list.Where(predicate); 
    } 
} 
+4

爲什麼你希望得到所有四個'Person'對象時只有兩個四的滿足您的謂詞所定義的標準是什麼?你期望有多少個對象IsAdult()返回true? –

回答

4

如果以這種方式連接代表,將會執行所有這些代碼,但只會從最後一個之一得到結果。 查看有關此使用委託的票數: https://msdn.microsoft.com/en-us/library/ms173172.aspx

如果委託有返回值和/或輸出參數,返回調用最後方法的返回值和參數。

逆序會給你所有的結果:

Func<Person, bool> predicate = null; 
predicate += IsAdult; 
predicate += MethodTrue; 

但我看不出這樣做LINQ這樣任何意義。你可以只寫

Func<Person, bool> predicate = x=> IsAdult(x) || MethodTrue(x); 

或者&&,這取決於你真正想要達到的事情。

+2

將其倒序排列只會是一個樂隊援助解決方案。如果將邏輯添加到過濾出來的MethodTrue中,則會導致相同的問題。逆轉它們的唯一原因將起作用,因爲該方法總是發佈真實的。真正的解決辦法是逐步進行你想要做的邏輯比較。 –

+1

幹得好。 MSDN的參考是這裏的關鍵。非常有趣的行爲。 –

+0

同意,MSDN文章闡明出來很好,串聯與方法'+ ='不走,除非你只是想最後的結果集中的最後評估的方法,它爲何與其他方法懶得再方式。 –

-2

當您提供您的謂詞兩個功能,它們與按位AND (&&)這意味着對象只兩個函數返回包含評估。由於您正在篩選出Person對象18和更年輕的IsAdult(),因此只能從該函數返回兩條記錄。這意味着按位操作永遠不會返回超過這兩條記錄。

+1

兩者都執行,但只返回最後一個的結果,倒序將返回所有4個人。 –

+1

有趣的 - 這似乎是一個問題'+ ='運算符被應用於函數的方式。正如在其他答案中提到的那樣,'Func predicate = x => MethodTrue(x)&& IsAdult(x);'如我所期望的那樣返回兩條記錄。 –

+0

@RickLiddle不,這不是代表如何組合,它是關於調用在調用列表多種方法委託的行爲,以及它是如何確定哪些值在這種情況下返回。 – Servy

0

您的結果集正在根據您的謂詞過濾掉。你有你的謂詞定義爲:IsAdult這將做年齡比較MethodTrue這將始終返回true。因此,如果人員年齡未通過age > 18檢查,那麼您的where語句在您的列表中的該項目上失敗。

所以你的where子句只會返回2個值,因爲根據你的邏輯函數,只有2個人是成年人。

結果基於謂詞:

var list = new List<Person> 
    { 
     new Person() { Age = 20, Name = "Artur" }, 
     new Person() { Age = 30, Name = "Adam" } 
    }; 

如果你正在尋找做一個​​聲明,你可以遵循的馬克西姆Simkin提到返回所有值寫你的斷言。

Func<Person, bool> predicate = x => IsAdult(x) || MethodTrue(x); 
2

您鏈接兩個謂詞的方式,它只關心最後一個(這裏的第二個謂詞)。

即使情況並非如此,MethodTrue()始終返回true,只有兩個人通過IsAdult條件,這就是爲什麼它只返回兩個項目。順便說一下,你並不需要變量predicate。你可以寫這樣的事情:

var res = list.Where(p => MethodTrue(p) && (IsAdult(p))); 
+1

@Downvoter謹慎解釋? – Encrypt0r