C# 7.0 以降で利用可能な「タプル(ValueTuple)」を使用すると、メソッドから複数の値を簡単に返すことができます。
従来、複数の値を返すためには out 引数を使用するか、戻り値専用のクラスや構造体を定義する必要がありました。タプルを利用することで、より簡潔な構文で、型安全かつ可読性の高いコードを記述できます。
本記事では、タプルの定義方法、値の受け取り方、そして変数の分解(Deconstruction)について解説します。
実装例:商品名と色を同時に返すメソッド
以下のコードは、GetItem メソッドから「名前」と「色」という2つの情報をタプルとして返し、呼び出し側でそれを受け取る例です。
using System;
namespace TupleExample
{
class Program
{
static void Main(string[] args)
{
// パターン1: タプルオブジェクトとして受け取る
// メソッド定義側で要素名を指定しているため、.Name, .Color でアクセス可能
var item = GetItem();
Console.WriteLine($"[オブジェクト] 商品: {item.Name}, 色: {item.Color}");
// パターン2: 分解(Deconstruction)を利用する
// タプルの内容を個別の変数に直接展開して受け取る
// 変数名はメソッド側の定義(Name, Color)と異なっていても構わない
var (productName, productColor) = GetItem();
Console.WriteLine($"[分解] 商品: {productName}, 色: {productColor}");
// パターン3: 不要な値を破棄(Discard)する
// 色だけ知りたい場合、名前部分はアンダースコア (_) で破棄できる
var (_, justColor) = GetItem();
Console.WriteLine($"[破棄] 色のみ: {justColor}");
}
// メソッドの戻り値の型を (string Name, string Color) と定義
// これにより、呼び出し側は Item1, Item2 ではなく意味のある名前でアクセスできる
static (string Name, string Color) GetItem()
{
// タプルリテラル (値1, 値2) を作成して返す
return ("Banana", "Yellow");
}
}
}
解説とポイント
1. 戻り値の定義と名前付きタプル要素
メソッドの戻り値型を (string, string) と書くだけでもタプルになりますが、(string Name, string Color) のように要素に名前を付けることを推奨します。 名前がない場合、呼び出し側では item.Item1, item.Item2 といった無機質な名前でアクセスしなければならず、可読性が低下するためです。
2. 分解(Deconstruction)
var (name, color) = GetItem(); の構文を使用すると、返されたタプルの各要素を、その場で定義したローカル変数に代入できます。これにより、タプルオブジェクトを経由せず、直感的に値を扱うことができます。
3. パフォーマンス(ValueTuple)
C# 7.0 以降のタプルは System.ValueTuple 構造体によって実現されています。これは値型(struct)であるため、ヒープメモリの割り当てが発生する古い System.Tuple クラス(参照型)と比較して、ガベージコレクションへの負荷が少なく軽量です。
まとめ
タプルは、メソッドから「一時的に複数の値を返したい」という場面で非常に強力な機能です。
- 定義:
(Type Name, Type Name) MethodName() { ... } - 利用:
var result = MethodName();またはvar (a, b) = MethodName(); - メリット: クラス定義が不要で、軽量かつ型安全。
複雑なデータ構造が必要な場合はクラスの使用を検討すべきですが、単純なペア値などを返す場合はタプルを積極的に利用してください。
