yield return で IComparer

C#yield return ってなんかステキっぽいけどいまひとつ使いどころに巡り会えない*1、と思ってたけどこないだふと IComparer の実装に使えるんじゃないかとおもた。

例えば以下のようなクラスがあったとして、

    public class Foo
    {
        public int A { get; set; }
        public int B { get; set; }
        public int C { get; set; }
    }

こいつをソートするための IComparer の実装は例えば以下のように書ける。

    public class FooComparer : IComparer<Foo>
    {
        public int Compare(Foo x, Foo y)
        {
            return x.A != y.A ? x.A.CompareTo(y.A)
                : x.B != y.B ? x.B.CompareTo(y.B)
                : x.C != y.C ? x.C.CompareTo(y.C)
                : x.ToString().CompareTo(y.ToString()); // 最後はてきとう
            
        }
    }

これを yield returnを使って書き換えるとこんな感じに書ける。

    public class FooComparer : IComparer<Foo>
    {
        public int Compare(Foo x, Foo y)
        {
            foreach (int result in GetComparedResults(x, y))
            {
                if (result != 0)
                {
                    return result;
                }
            }
            return x.ToString().CompareTo(y.ToString());
        }

        private IEnumerable<int> GetComparedResults(Foo x, Foo y)
        {
            yield return x.A.CompareTo(y.A);
            yield return x.B.CompareTo(y.B);
            yield return x.C.CompareTo(y.C);
        }
    }

上記の例だと単純すぎて余計冗長になってるけど、比較対象プロパティが多かったり条件がややこしくなってきたりすると結構すっきり書けるんじゃなかろか。こういう使い方するもんなのかな・・?

*1:GUI でイベントドリブンな状態管理みたいなのにはかなり使えそう。ただ今やってるのは極めてステートレスな web なので、なかなか使いどころがない。発想が貧困かしら。