アプリケーション部の田口(@t_tetsuzin)です。 社内では数少ないF#erとして潜伏中です。

待ちに待った VisualStudio2017 がリリースされましたね！

Graniではさっそく C# 7.0 を本番環境に投入しています。

そんな待望の C# 7.0 で使えるようになった新機能は

タプル(ValueTuple)・タプルの分解

Task-like

ローカル関数

拡張されたswitch文（パターンマッチ）

etc…

と大きいのから小さいのまで多岐にわたりますが、 今回はタプルの便利な使い方について紹介したいと思います。

タプル以外の今回の目玉機能である Task-like はちょうど公開された弊社CTOの記事でどうぞ！

どういう風に便利なのか

※ ValueTuple は .NET Framework 4.7 未満で使用する場合は

Nuget から System.ValueTuple をパッケージをプロジェクトに追加する必要があります。

ソーシャルゲームではユーザーの情報など大量のデータを様々なところから呼び出す必要があるので、 こういう複数の非同期処理を呼ぶ場所がよく出てきます。

public async Task< int > HogeAsync() { await HeavyFunctionAsync(); return 10 ; } public async Task< string > FugaAsync() { await HeavyFunctionAsync(); return "Fuga" ; } public async Task< int []> MogeAsync() { await HeavyFunctionAsync(); return new [] { 10 , 20 , 30 }; }

非同期処理を並列に実行するため、今まではこのように書いていました。

public async Task Before() { var hogeTask = HogeAsync(); var fugaTask = FugaAsync(); var mogeTask = MogeAsync(); await Task.WhenAll(hogeTask, fugaTask, mogeTask); var hoge = hogeTask.Result; var fuga = fugaTask.Result; var moge = mogeTask.Result; await SomeFunctionAsync(hoge, fuga, moge); }

長いですね。とてもイケてるコードには見えません。

しかし、タプルと分解、そして拡張メソッドを組み合わせることで……

public async Task After() { var (hoge, fuga, moge) = await (HogeAsync(), FugaAsync(), MogeAsync()).WhenAll(); await SomeFunctionAsync(hoge, fuga, moge); }

こんな風に書くことができるようになりました。

追加した拡張メソッド

public static class ValueTupleExtensions { public static async Task<(T1, T2)> WhenAll<T1, T2>( this (Task<T1>, Task<T2>) tasks) { await Task.WhenAll(tasks.Item1, tasks.Item2).ConfigureAwait( false ); return (tasks.Item1.Result, tasks.Item2.Result); } public static async Task<(T1, T2, T3)> WhenAll<T1, T2, T3>( this (Task<T1>, Task<T2>, Task<T3>) tasks) { await Task.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3).ConfigureAwait( false ); return (tasks.Item1.Result, tasks.Item2.Result, tasks.Item3.Result); } public static async Task<(T1, T2, T3, T4)> WhenAll<T1, T2, T3, T4>( this (Task<T1>, Task<T2>, Task<T3>, Task<T4>) tasks) { await Task.WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4).ConfigureAwait( false ); return (tasks.Item1.Result, tasks.Item2.Result, tasks.Item3.Result, tasks.Item4.Result); } }

上の例では4組のタプルまでしか挙げていませんが、8組程度なら用意してしまって良いと思います。

今回はタプルしか紹介していませんが、C# 7.0 には他にも有力な新機能が多く含まれているので、積極的に使っていきましょう！ もちろん弊社のもうすぐリリースされる新タイトル黒騎士と白の魔王でも C# 7.0 が使われています！