同期メソッドを非同期メソッドに変換する（ex. Action → Func<Task>）

同期メソッドを非同期メソッドに変換する拡張メソッドです。
呼び出し元から非同期メソッドを受け取る汎用的な処理を実装しているとき、同期メソッドも受け取ることができるようにしておきたくなることがあります。ニッチな用途ですが個人的には必要となる場面が多く、拡張メソッドとして実装しました。

```c#
Action action = hoge;
Func<Task> asyncAction = action.ToAsync();
```

これは同期メソッドを非同期メソッドとして保持しておきたいときのためのもので、同期メソッドをただ単に非同期実行したいだけであれば Task.Run を使えばよいと思います。

### 実装

* Action → Func&lt;Task&gt;
* Action&lt;T1&gt; → Func&lt;T1, Task&gt;
* Action&lt;T1, T2&gt; → Func&lt;T1, T2, Task&gt;
* Func&lt;TResult&gt; → Func&lt;Task&lt;TResult&gt;&gt;
* Func&lt;T1, TResult&gt; → Func&lt;T1, Task&lt;TResult&gt;&gt;
* Func&lt;T1, T2, TResult&gt; → Func&lt;T1, T2, Task&lt;TResult&gt;&gt;

T1 ～ T16 までの実装は [GitHub](https://github.com/mxProject/Misc/blob/master/source/DelegateExtension.cs) にあります。2151行目（#region action -> async func）～2760行目です。

```c#
public static class DelegateExtensions
{

    #region action -> async func

    /// <summary>
    /// Converts the specified action to a async func.
    /// </summary>
    /// <param name="action"></param>
    /// <returns></returns>
    public static Func<Task> ToAsync(this Action action)
    {
        return () => Task.Run(action);
    }

    /// <summary>
    /// Converts the specified action to a async func.
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <param name="action"></param>
    /// <returns></returns>
    public static Func<T1, Task> ToAsync<T1>(this Action<T1> action)
    {
        return (arg1) => Task.Run(() => action(arg1));
    }

    /// <summary>
    /// Converts the specified action to a async func.
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    /// <param name="action"></param>
    /// <returns></returns>
    public static Func<T1, T2, Task> ToAsync<T1, T2>(this Action<T1, T2> action)
    {
        return (arg1, arg2) => Task.Run(() => action(arg1, arg2));
    }

    #endregion

    #region func -> async func

    /// <summary>
    /// Converts the specified func to a async func.
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="func"></param>
    /// <returns></returns>
    public static Func<Task<TResult>> ToAsync<TResult>(this Func<TResult> func)
    {
        return () => Task.Run(() => func());
    }

    /// <summary>
    /// Converts the specified func to a async func.
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="func"></param>
    /// <returns></returns>
    public static Func<T1, Task<TResult>> ToAsync<T1, TResult>(this Func<T1, TResult> func)
    {
        return (arg1) => Task.Run(() => func(arg1));
    }

    /// <summary>
    /// Converts the specified func to a async func.
    /// </summary>
    /// <typeparam name="T1"></typeparam>
    /// <typeparam name="T2"></typeparam>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="func"></param>
    /// <returns></returns>
    public static Func<T1, T2, Task<TResult>> ToAsync<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        return (arg1, arg2) => Task.Run(() => func(arg1, arg2));
    }

    #endregion
}
```

### サンプル

```c#
private async Task Sample()
{
    Debug.WriteLine("enter");

    SampleExecutor executor;

    executor = SampleExecutor.NewSync(HeavyFunc);
    Debug.WriteLine(await executor.ExecuteAsync(5).ConfigureAwait(false));

    executor = SampleExecutor.NewAsync(HeavyAsyncFunc);
    Debug.WriteLine(await executor.ExecuteAsync(10).ConfigureAwait(false));

    // ただ単に非同期で実行したいだけなら、Task.Run を使えばよいと思います。
    Debug.WriteLine(await Task.Run(() => HeavyFunc(15)).ConfigureAwait(false));

    Debug.WriteLine("exit");
}

private string HeavyFunc(int arg)
{
    System.Threading.Thread.Sleep(5000);
    return arg.ToString("d5");
}

private async Task<string> HeavyAsyncFunc(int arg)
{
    await Task.Delay(5000);
    return arg.ToString("d5");
}

private class SampleExecutor
{
    internal static SampleExecutor NewSync(Func<int, string> action)
    {
        return new SampleExecutor(action.ToAsync());
    }

    internal static SampleExecutor NewAsync(Func<int, Task<string>> asyncAction)
    {
        return new SampleExecutor(asyncAction);
    }

    private SampleExecutor(Func<int, Task<string>> asyncAction)
    {
        m_AsyncAction = asyncAction;
    }

    private readonly Func<int, Task<string>> m_AsyncAction;

    internal Task<string> ExecuteAsync(int arg)
    {
        return m_AsyncAction(arg);
    }
}
```
出力結果

```
enter
00005
00010
00015
exit
```