2017-02-21 133 views
1

我有這個代碼,它應該返回一個值類型,在每個步驟中應用在steps中指定的轉換。意外的結果與Where()

private static T Transformed<T>(T x, params Func<T, T>[] steps) where T : struct 
{ 
    if ((steps?.Length ?? 0) == 0) 
    { 
     return x; 
    } 

    var reallyEmpty = steps.Where(f => (x = f(x)).Equals(int.MinValue)); 
    return x; 
} 

我只需要Where延伸至每一步都離不開一個循環,所以我使用的很可能永遠不會滿足的條件(Equals(int.MinValue))。 但是,如果我有這個調用代碼,我得到5而不是15,我如何看待。

int res1 = Transformed(5, x => x * 2, x => x + 5); 
Console.WriteLine(res1); 

我的問題是爲什麼? Where是否經過每個元素並檢查它?

+2

你不是迭代'reallyEmpty',所以副作用'x = f(x)'從不執行。 – Lee

+0

如果你是linq的忠實粉絲,你可以創建[ForEach](http://stackoverflow.com/a/1509458/1997232)擴展,永遠不要再混淆你自己或他人。 – Sinatr

回答

12

Where被懶惰地評估 - 你永遠不會使用它的結果,所以謂詞永遠不會被評估。

可以通過計算結果或類似力迭代:自己

​​

...但它會更清楚顯著只是循環:

foreach (var step in steps) 
{ 
    x = step(x); 
} 

畢竟,你」不要真的通過使用Where避免循環 - 你只是隱藏它,並在這樣做,你過分複雜的代碼,你不明白的程度它再一次。

2

如果你真的使用LINQ設置,有可能你想用什麼Aggregate

private static T Transformed<T>(T x, params Func<T, T>[] steps) where T : struct 
{ 
    return steps?.Aggregate(x, (accum, f) => f(accum)) ?? x; 
} 

我通常不會找骨料特別可讀的,但我想這是值得一提。