メモ: IEnumerableの要素に変更を加えたIEnumerableを取得する

C#でハマったことのメモです。

状況

IEnumerable.Selectで取得したIEnumerable sourceがある。

sourceの各要素が特定の条件を満たすとき、その要素のプロパティに変更を加える。

最終的に、変更を適用した後の要素を集めたIEnumerableを取得したい。

問題

IEnumerableは列挙のための型なので、反復中に削除したり更新したりといった変更を加えることができません。

解決方法

特定の条件を満たした要素を使って、新しいIEnumerableを作ります。

IEnumerable<Foo> result = Enumerable.Empty<Foo>();

foreach (var one in source) // IEnumerable<Foo> source
{
    if (/* 条件式 */)
    {
        var tmp = Enumerable.Repeat<Foo>(
            new Foo
            {
                // 元要素から変更するプロパティ
                Prop0 = something,
                
                // 変更しないプロパティ
                Prop1 = one.Prop1,
                Prop2 = one.Prop2
            }, 1);
        
        result = result.Concat<Foo>(tmp);
    }
}

Repeatで引数に1を指定する方法は、bleisさんが教えてくださいました(https://twitter.com/bleis/status/377687644769357824)。大変助かりました。ありがとうございます!

特定の条件でフィルタリングしたいだけで、要素の変更が不要なときは、Whereを使えばいいんですね。wonderful_pandaさん、ありがとうございます。