C#でタプル(Tuple)を使う方法

「タプル」と呼ばれる技術を学んでいきます。タプルは値を同時に複数持つことのできるデータ型の一種です。メソッドの戻り値などで「複数を返したい」という場合に便利なので知っておくべき内容です。

タプルの基礎知識

タプルは複数の値をまとめて持つことのできるデータ型の一種で、C#7.0というバージョンから登場した技術です。Microsoftのドキュメントでは以下のように記述されています。

軽量データ構造に複数のデータ要素をグループ化するための簡潔な構文

タプル型 (C# リファレンス)|Microsoft Docs

C#では以下のようにタプルを記述します。メソッドに渡す「引数」のような形で記述する機能で、弧の中に「型 変数名」をカンマ区切りで並べていきます。

(double x, double y)

例えばメソッドの戻り値として以下のように記述でき、複数の戻り値をいっぺんに返すことができるので便利です。

private (double x, double y) GetPoint()

タプルには記述方法がたくさんあるため、サンプルコードを交えながら解説していきます。

タプルの使い方

タプルは複数の値を同時に持つことのできますが、値が1つの場合や値がない場合は使用することができませんので注意が必要です。かならず2つ以上の値をまとめる時に使用するようにしてください。

匿名型のタプル

いくつかのコンソールアプリケーションを作成していきます。まずはじめは一番シンプルな形の使い方を紹介します。これは値に変数名を付けずに匿名でタプルの値を作成する方法です。

using System;

namespace App23
{
    class Program
    {
        static void Main(string[] args)
        {
            //(型, 型)で定義
            (int, int) first = (100, 10);

            //要素の取り出し方
            Console.WriteLine("Item1:" + first.Item1.ToString());
            Console.WriteLine("Item2:" + first.Item2.ToString());

            Console.ReadLine();
        }
    }
}

タプルの作成方法を「(型, 型)」と「変数名」で左辺を形成し、右辺を「(100, 10)」と型に対応する値をカンマ区切りで並べています。

こういう場合に値を取り出すには「(変数名).Item1」と記述する必要があります。左からItem1、Itemo2、Item3・・・と続いていくことになります。Item1、Item2ともint型で定義していたので、出力する際に「.ToString()」を付けています。

値に名称を付けるタプル

では別のタプルの使い方を紹介します。新規のコンソールアプリケーションを作成してみましょう。今回は値に名称を付けてタプルを作成する方法です。こちらのほうが可読性は高くなります。

using System;

namespace App24
{
    class Program
    {
        static void Main(string[] args)
        {
            //(型 引数名, 型 引数名)で定義
            (int sum, int count) second = (100, 10);

            //値を取り出す方法
            Console.WriteLine("sum:" + second.sum.ToString());
            Console.WriteLine("count:" + second.count.ToString());

            Console.ReadLine();
        }
    }
}

今回はタプルを構成する値に対して名称を付与しています。一つ目にsum、二つ目にcountと名称を与えることで、値に対して意味を持たせるようにしました。こういう場合に値を取り出すには、「(変数名).(名称)」で取得できます。

なお、タプルは値を形成して保持するだけでなく、その値を書き換えることも可能です。新しいアプリケーションを作成して以下を記述してみてください。

using System;

namespace App25
{
    class Program
    {
        static void Main(string[] args)
        {
            //(型 引数名, 型 引数名)のタプル
            (string name, int number) tuple = ("First", 1);

            //変更前
            Console.WriteLine("name:" + tuple.name);
            Console.WriteLine("number:" + tuple.number.ToString());
            Console.WriteLine();

            //値を変更する
            tuple.name = "changed";
            tuple.number = 1000;

            //変更後
            Console.WriteLine("name:" + tuple.name);
            Console.WriteLine("number:" + tuple.number.ToString());
            Console.ReadLine();
        }
    }
}

値を変更するにはタプルから変更したい値の要素名を左辺に指定し、右辺で設定したい値を記述するだけです。これで値が変更されています。今回はnameとnumberとしていますが、Item1やItem2の場合でも同様です。

メソッドの戻り値でタプルを使う方法

最後にメソッドの戻り値として使用する方法のサンプルを紹介して終わりにしたいと思います。新規のコンソールアプリケーションを作成して以下を作成してみてください。

using System;

namespace App26
{
    class Program
    {
        static void Main(string[] args)
        {
            //タプルを作成する
            (int sum, int count) val = GetValue();

            //値を取り出して表示する
            Console.WriteLine(val.sum.ToString());
            Console.WriteLine(val.count.ToString());

            Console.ReadLine();
        }

        //タプルを戻り値とするメソッド
        private static (int sum, int count) GetValue()
        {
            return (100, 5);
        }
    }
}

Program.csのProgramクラス内にメソッドを作成しました。メソッドの戻り値としてタプルを使用する場合は、戻り値の型としてタプルを記述するだけで使用可能となります。あとなメソッド内部の戻り値でタプルを返却するだけです。

サンプルでは「GetValue」メソッドでタプルを返すようにして、「(int sum, int count) val = GetValue();」で受け取れるようにしています。メソッドで複数の値を戻す必要のある場面では、タプルを使用して値をペアにして戻してあげるのがよいでしょう。

タプルで必要な値を返そう

以上、タプル(Tuple)を使用する方法を解説しました。タプルを使用することで、同時に複数の値をペアにして保有することができるので、いざとなったときに非常に便利です。

複数の値を同時に戻す方法として、クラスを作成して値を設定する方法もありますが、それに比べるタプルのほうが軽量で手軽に使用可能です。中でも最も効果を発揮するのがメソッドの戻り値になります。

メソッド内部で複雑な処理をした場合に複数の値を戻したいことがあるので、非常に便利になるので今の段階でタプルを覚えておくと一つの強力な武器になります。