演算子のオーバーロードを乱用してみた

C#演算子のオーバーロードの規則が厳しくてつらいことがあるんですけど、回避できるかも!
・・・と思いついて、やってみたら出来なかった、という話です。


やりたいことは関数合成です。
F# の関数合成みたいに、>> とか << で合成できたらわかりやすくていいよなぁ、とか思うんですけど、C# で << とか >> は右項が int に限定されています。
なので、関数が int に暗黙変換できれば解決できるかも?と思ってやってみたんですが、非常に残念な感じになりました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OpOverloadHack
{
    class Program
    {
        static void Main(string[] args)
        {
            F f = new F(arg => ((int)arg) + 10);
            F g = new F(arg => ((int)arg) * 2);

            Console.WriteLine((f >> g)[3]); // (3 + 10) * 2 = 26
            Console.WriteLine((f << g)[3]); // (3 * 2) + 10 = 16
        }
    }
    class F
    {
        static readonly IDictionary<int, F> instances = new Dictionary<int, F>();
        static int nextId = 0;
        readonly int id;
        readonly Func<object, object> call;
        public F(Func<object, object> f)
        {
            this.call = f;
            this.id = nextId++;
            instances[this.id] = this;
        }

        public object this[object arg]
        {
            get { return call(arg); }
        }

        public static F operator >> (F f, int id)
        {
            var g = instances[id];
            return new F(arg => g.call(f.call(arg)));
        }

        public static F operator <<(F f, int id)
        {
            var g = instances[id];
            return new F(arg => f.call(g.call(arg)));
        }

        public static implicit operator int(F f) { return f.id; }
    }
}

型情報が保てませんでした・・・
まぁ、もしできたとしてもやるべきではないですけどね。