2017-02-21 18 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; 
} 

私だけので、私はおそらく本当であることができませんでした条件(Equals(int.MinValue))を使用し、ループを使用せずに、各ステップを介して取得するWhere拡張子を必要としています。 しかし、私はこの呼び出しコードを持っていれば、5で、15ではなく、私は期待しています。

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

私の質問はなぜですか? Whereは各要素を調べて確認していませんか?

+2

副作用 'x = f(x)'が決して実行されないように、 'reallyEmpty'を反復しているわけではありません。 – Lee

+0

あなたがlinqの大ファンなら、あなたは[ForEach](http://stackoverflow.com/a/1509458/1997232)の拡張機能を作成することができます。 – Sinatr

答えて

12

Whereは遅延評価されています。結果は決して使用されないため、述語は決して評価されません。 「結局のところ

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

、あなた:

あなたはは、結果または類似をカウントすることにより、力の反復可能性:

​​

は...しかし、それだけでループ自身にかなり明確になります実際にを使用してループを回避する - あなたはそれを隠しているだけで、あなたが理解していない程度にあなたのコードを複雑にしていますそれ以上はありません。私は一般的に集約特に読める見つからない

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

、私はそれが言及する価値があった考え出し:あなたは本当にLINQを使用して設定している場合

2

、それはあなたがAggregateを使ってやりたいことも可能です。

関連する問題