C#7のタプルの使いどころ

posted in: C# | 0

こんにちは。阿部です。

C#では、バージョン7.0からタプルという機能が使えるようになりました。
この機能は、今まで一つのオブジェクトしか渡すことができなかった状況で、複数のオブジェクトを渡すことを可能にします。

複数戻り値

タプルの代表的な使用方法は、メソッドから複数の値を返すことです。
これまで、メソッドの戻り値は0個(voidの場合)か1個でしたが、タプルを使用することで2個以上の戻り値を記述することができます。

メソッドを呼び出す側では、複数の変数に結果を受け取ることができます。
これを、タプルの分解(deconstruction)と言います。

ところで、「GetName()GetAge()にメソッドを分ければ良いのでは?」という声が聞こえてきそうですが、「同時に取得したほうが計算コストが低い。」とか「2回に分けて取得すると値が変わってしまう。」といった理由で分けられないシチュエーションもあると思います。

コレクションの要素として利用する

タプルは、Listなどのコレクションの要素として利用することができます。
コレクションはforeachで回すことが多いと思いますが、取り出した要素を複数変数で受け取ることができます。

一方で、LINQの条件式内では、複数変数に分解することができないため、タプルとして受け取ることになります。この場合、クラスメンバのように、”タプル.要素名” で中身にアクセスできます。

Dictionaryで複数キーを実現

C#の連想配列であるDictionaryの場合は、KeyにもValueにもタプルを利用することができます。Keyとしてタプルを利用した場合は、データベース(RDB)における複数キーのような構造を表現することができます。

使いどころの見極め

タプルを使えるとしても、基本的には、まず構造体やクラスにすることを検討すべきだと思います。
ここまでの例であれば、(string name, int age)ではなく、次のような型を用意したほうが適当かもしれません。

こうすれば、ただの「名前」と「年齢」ではなく、「人」というデータであることが表現できます。タプルにすると、この情報は失われてしまいます。

一方、ここで、PersonではなくNameAndAgeNameAgePairという、あまり意味のない名前になってしまうなら、おそらくタプルの出番です。

このような場合は、積極的にタプルを使用しても良いと思います。

楽をするために使う

メソッドの戻り値をまとめるのに、わざわざ型を作りたくないですよね。
タプルを使って楽をしましょう。
しかし、タプルを使用すると、型名として持つべき情報が失われてしまいます。そこで、タプルの乱用を防ぐために、ある程度の指針は必要だと思います。例えば、

  • クラス内のみでの使用。(privateな範囲での使用。)
  • 型名がなくても、要素名だけで十分な情報を表現できている場合。
  • とにかく急いでいる場合や、使い捨てのコードの場合。

最後の指針は難しいところです。今書いているコードが、絶対に再利用されないと保証できるでしょうか。意外と、そのまま製品に使われてしまったりして……。

最後に

タプルの使い方は、型推論のvarをどう使うかという議論と似たところがあります。
いずれも、コードを簡潔にし、冗長性を取り除くことができますが、使い方によっては、コードの持つ情報量が減ってしまう可能性があります。

むしろ、型推論であれば、全部varにしてしまっても、IntelliSenseで、すぐに型名が見られるのですが、タプルの場合は、「型名」という情報が本当に消え去ってしまいます。
いろいろなところで使えそうな機能ではあるのですが、実際に使うべき場面の見極めが重要です。

LINEで送る
Pocket