コードブロックを受け取るメソッドは便利

Ruby を使うようになってから、C# でもコードブロックを受け取るメソッドを多様するようになった。

public static class DatabaseHelper
{
    public static bool Transaction(this Database db, Action<Database> block, int retryCount)
    {
        bool success = false;
        for (int i = 0; i <= retryCount; i++)
        {
            using(TransactionScope ts = new TransactionScope())
            {
                try
                {
                    block(db);
                    success = true;
                    ts.Complete();
                    break;
                }
                catch (Exception ex)
                {
                    // 例外情報を保持しておいて、リトライに全て失敗したら
                    // まとめてスローする方がいいかも。
                    success = false;
                }
            }
        }
        return success;
    }
}
// トランザクションをかけてクエリを実行。
// 失敗したら3回までリトライする。
Database database = new Database(connectionString);
database.Transaction(db =>
{
    db.ExecuteCommand(command);
}, 3);

匿名メソッドは、外側のローカル変数も参照できるので、非常に強力。

この手法をリファクタリングで使えば、メソッドの抽出では共通化できなかったコードでも、共通化できたりする。かなり便利。