Let's first turn your existing memoization implementation that uses a lambda into an explicit capture class (this is almost identical to what the C# compiler creates automatically when it sees a lambda):
class CachedFunc<T>
{
private List<T> cache;
private Func<int, T> original;
private T Call(int n)
{
while (n >= cache.Count) cache.Add(original(cache.Count));
return cache[n];
}
public static Func<int, long> Create(Func<int, T> original)
{
return new CachedFunc<T>() { cache = new List<T>(), original = original }.Call;
}
}
Now, we just need to add implicit conversion:
class CachedFunc<T>
{
private List<T> cache;
private Func<int, T> original;
private T Call(int n) {
while (n >= cache.Count) cache.Add(original(cache.Count));
return cache[n];
}
public static implicit operator CachingFunc<T>(Func<int, T> original)
{
return new CachedFunc<T>() { cache = new List<T>(), original = original };
}
public static implicit operator Func<int, T>(CachingFunc<T> memo)
{
return memo.Call;
}
}