以前、C# で関数をメモ化するサンプルを紹介しました。
メモ化って便利。でもこのままだと、関数を使うときに毎回メモ化しなければいけません。ちょっと面倒です。クラスのメソッドをあらかじめメモ化しておき、利用側はメソッドを呼び出すだけにしたい。
そこで、Func
using System; using System.Collections.Generic; using System.Threading; namespace MemoSample { public static class MemoUtil { // 関数をメモ化します。 public static Func<T, TResult> Memoization<T, TResult>(Func<T, TResult> method) { Dictionary<T, TResult> cache = new Dictionary<T, TResult>(); return x => { if (!cache.ContainsKey(x)) { cache[x] = method(x); } return cache[x]; }; } } public class Greeting { // メソッドを格納するフィールドを用意して、 // そこにメモ化した匿名メソッドをセット。 public readonly Func<string, string> Greet = MemoUtil.Memoization<string, string>(name => { Thread.Sleep(2000); return string.Format("Hello, {0}", name); }); } class Program { static void Main(string[] args) { Greeting g = new Greeting(); Console.WriteLine(g.Greet("Ichiro")); Console.WriteLine(g.Greet("Hideki")); Console.WriteLine(g.Greet("Ichiro")); Console.ReadLine(); } } }
厳密には、メモ化しているのは匿名メソッドですけど…。クラスを使う側からすれば、使い勝手はたいして変わらないはず。フィールドの宣言と初期化を同時に行っているので、メソッドの定義に近い記述ができています。